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 (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 : pDispatcher->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 : 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 : OUString sName = p->GetName();
1140 0 : SbMethod* pMeth = p ? PTR_CAST( SbMethod, p ) : NULL;
1141 0 : if( pMeth )
1142 : {
1143 : sal_uInt16 l1,l2;
1144 0 : pMeth->GetLineRange(l1,l2);
1145 0 : if( (l1 <= nLine+1) && (nLine+1 <= l2) )
1146 : {
1147 0 : return sName;
1148 : }
1149 : }
1150 0 : }
1151 0 : return OUString("");
1152 : }
1153 :
1154 0 : void EditorWindow::SetScrollBarRanges()
1155 : {
1156 : // extra method, not InitScrollBars, because for EditEngine events too
1157 0 : if ( !pEditEngine )
1158 0 : return;
1159 :
1160 0 : if ( rModulWindow.GetHScrollBar() )
1161 0 : rModulWindow.GetHScrollBar()->SetRange( Range( 0, nCurTextWidth-1 ) );
1162 :
1163 0 : rModulWindow.GetEditVScrollBar().SetRange( Range( 0, pEditEngine->GetTextHeight()-1 ) );
1164 : }
1165 :
1166 0 : void EditorWindow::InitScrollBars()
1167 : {
1168 0 : if ( !pEditEngine )
1169 0 : return;
1170 :
1171 0 : SetScrollBarRanges();
1172 0 : Size aOutSz( GetOutputSizePixel() );
1173 0 : rModulWindow.GetEditVScrollBar().SetVisibleSize( aOutSz.Height() );
1174 0 : rModulWindow.GetEditVScrollBar().SetPageSize( aOutSz.Height() * 8 / 10 );
1175 0 : rModulWindow.GetEditVScrollBar().SetLineSize( GetTextHeight() );
1176 0 : rModulWindow.GetEditVScrollBar().SetThumbPos( pEditView->GetStartDocPos().Y() );
1177 0 : rModulWindow.GetEditVScrollBar().Show();
1178 :
1179 0 : if ( rModulWindow.GetHScrollBar() )
1180 : {
1181 0 : rModulWindow.GetHScrollBar()->SetVisibleSize( aOutSz.Width() );
1182 0 : rModulWindow.GetHScrollBar()->SetPageSize( aOutSz.Width() * 8 / 10 );
1183 0 : rModulWindow.GetHScrollBar()->SetLineSize( GetTextWidth( "x" ) );
1184 0 : rModulWindow.GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
1185 0 : rModulWindow.GetHScrollBar()->Show();
1186 : }
1187 : }
1188 :
1189 0 : void EditorWindow::ImpDoHighlight( sal_uLong nLine )
1190 : {
1191 0 : if ( bDoSyntaxHighlight )
1192 : {
1193 0 : OUString aLine( pEditEngine->GetText( nLine ) );
1194 0 : bool const bWasModified = pEditEngine->IsModified();
1195 0 : pEditEngine->RemoveAttribs( nLine, true );
1196 0 : std::vector<HighlightPortion> aPortions;
1197 0 : aHighlighter.getHighlightPortions( aLine, aPortions );
1198 :
1199 0 : for (std::vector<HighlightPortion>::iterator i(aPortions.begin());
1200 0 : i != aPortions.end(); ++i)
1201 : {
1202 0 : Color const aColor = rModulWindow.GetLayout().GetSyntaxColor(i->tokenType);
1203 0 : pEditEngine->SetAttrib( TextAttribFontColor(aColor), nLine, i->nBegin, i->nEnd, true );
1204 : }
1205 :
1206 0 : pEditEngine->SetModified( bWasModified );
1207 : }
1208 0 : }
1209 :
1210 0 : void EditorWindow::UpdateSyntaxHighlighting ()
1211 : {
1212 0 : unsigned nCount = pEditEngine->GetParagraphCount();
1213 0 : for (unsigned i = 0; i < nCount; ++i)
1214 0 : DoDelayedSyntaxHighlight(i);
1215 0 : }
1216 :
1217 0 : void EditorWindow::ImplSetFont()
1218 : {
1219 : OUString sFontName(
1220 : officecfg::Office::Common::Font::SourceViewFont::FontName::get().
1221 0 : get_value_or( OUString() ) );
1222 0 : if ( sFontName.isEmpty() )
1223 : {
1224 0 : Font aTmpFont( OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, Application::GetSettings().GetUILanguageTag().getLanguageType(), 0 , this ) );
1225 0 : sFontName = aTmpFont.GetName();
1226 : }
1227 0 : Size aFontSize(0, officecfg::Office::Common::Font::SourceViewFont::FontHeight::get());
1228 0 : Font aFont( sFontName, aFontSize );
1229 0 : aFont.SetColor( GetSettings().GetStyleSettings().GetFieldTextColor() );
1230 0 : SetPointFont( aFont );
1231 0 : aFont = GetFont();
1232 :
1233 0 : rModulWindow.GetBreakPointWindow().SetFont( aFont );
1234 0 : rModulWindow.GetLineNumberWindow().SetFont( aFont );
1235 :
1236 0 : if ( pEditEngine )
1237 : {
1238 0 : bool const bModified = pEditEngine->IsModified();
1239 0 : pEditEngine->SetFont( aFont );
1240 0 : pEditEngine->SetModified( bModified );
1241 0 : }
1242 0 : }
1243 :
1244 0 : void EditorWindow::DoSyntaxHighlight( sal_uLong nPara )
1245 : {
1246 : // because of the DelayedSyntaxHighlight it's possible
1247 : // that this line does not exist anymore!
1248 0 : if ( nPara < pEditEngine->GetParagraphCount() )
1249 : {
1250 : // unfortunately I'm not sure that excactly this line does Modified() ...
1251 0 : if ( pProgress )
1252 0 : pProgress->StepProgress();
1253 0 : ImpDoHighlight( nPara );
1254 : }
1255 0 : }
1256 :
1257 0 : void EditorWindow::DoDelayedSyntaxHighlight( sal_uLong nPara )
1258 : {
1259 : // line is only added to 'Liste' (list), processed in TimerHdl
1260 : // => don't manipulate breaks while EditEngine is formatting
1261 0 : if ( pProgress )
1262 0 : pProgress->StepProgress();
1263 :
1264 0 : if ( !bHighlightning && bDoSyntaxHighlight )
1265 : {
1266 0 : if ( bDelayHighlight )
1267 : {
1268 0 : aSyntaxLineTable.insert( nPara );
1269 0 : aSyntaxIdleTimer.Start();
1270 : }
1271 : else
1272 0 : DoSyntaxHighlight( nPara );
1273 : }
1274 0 : }
1275 :
1276 0 : IMPL_LINK_NOARG(EditorWindow, SyntaxTimerHdl)
1277 : {
1278 : DBG_ASSERT( pEditView, "Noch keine View, aber Syntax-Highlight ?!" );
1279 :
1280 0 : bool const bWasModified = pEditEngine->IsModified();
1281 : //pEditEngine->SetUpdateMode(false);
1282 :
1283 0 : bHighlightning = true;
1284 0 : for ( SyntaxLineSet::const_iterator it = aSyntaxLineTable.begin();
1285 0 : it != aSyntaxLineTable.end(); ++it )
1286 : {
1287 0 : sal_uInt16 nLine = *it;
1288 0 : DoSyntaxHighlight( nLine );
1289 : }
1290 :
1291 : // #i45572#
1292 0 : if ( pEditView )
1293 0 : pEditView->ShowCursor( false, true );
1294 :
1295 0 : pEditEngine->SetModified( bWasModified );
1296 :
1297 0 : aSyntaxLineTable.clear();
1298 0 : bHighlightning = false;
1299 :
1300 0 : return 0;
1301 : }
1302 :
1303 0 : void EditorWindow::ParagraphInsertedDeleted( sal_uLong nPara, bool bInserted )
1304 : {
1305 0 : if ( pProgress )
1306 0 : pProgress->StepProgress();
1307 :
1308 0 : if ( !bInserted && ( nPara == TEXT_PARA_ALL ) )
1309 : {
1310 0 : rModulWindow.GetBreakPoints().reset();
1311 0 : rModulWindow.GetBreakPointWindow().Invalidate();
1312 0 : rModulWindow.GetLineNumberWindow().Invalidate();
1313 : }
1314 : else
1315 : {
1316 0 : rModulWindow.GetBreakPoints().AdjustBreakPoints( (sal_uInt16)nPara+1, bInserted );
1317 :
1318 0 : long nLineHeight = GetTextHeight();
1319 0 : Size aSz = rModulWindow.GetBreakPointWindow().GetOutputSize();
1320 0 : Rectangle aInvRect( Point( 0, 0 ), aSz );
1321 0 : long nY = nPara*nLineHeight - rModulWindow.GetBreakPointWindow().GetCurYOffset();
1322 0 : aInvRect.Top() = nY;
1323 0 : rModulWindow.GetBreakPointWindow().Invalidate( aInvRect );
1324 :
1325 0 : Size aLnSz(rModulWindow.GetLineNumberWindow().GetWidth(),
1326 0 : GetOutputSizePixel().Height() - 2 * DWBORDER);
1327 0 : rModulWindow.GetLineNumberWindow().SetPosSizePixel(Point(DWBORDER + 19, DWBORDER), aLnSz);
1328 0 : rModulWindow.GetLineNumberWindow().Invalidate();
1329 : }
1330 0 : }
1331 :
1332 0 : void EditorWindow::CreateProgress( const OUString& rText, sal_uLong nRange )
1333 : {
1334 : DBG_ASSERT( !pProgress, "ProgressInfo existiert schon" );
1335 : pProgress.reset(new ProgressInfo(
1336 0 : GetShell()->GetViewFrame()->GetObjectShell(),
1337 : rText,
1338 : nRange
1339 0 : ));
1340 0 : }
1341 :
1342 0 : void EditorWindow::DestroyProgress()
1343 : {
1344 0 : pProgress.reset();
1345 0 : }
1346 :
1347 0 : void EditorWindow::ForceSyntaxTimeout()
1348 : {
1349 0 : aSyntaxIdleTimer.Stop();
1350 0 : aSyntaxIdleTimer.GetTimeoutHdl().Call(&aSyntaxIdleTimer);
1351 0 : }
1352 :
1353 :
1354 :
1355 : // BreakPointWindow
1356 :
1357 :
1358 :
1359 0 : BreakPointWindow::BreakPointWindow (Window* pParent, ModulWindow* pModulWindow)
1360 : : Window(pParent, WB_BORDER)
1361 : , rModulWindow(*pModulWindow)
1362 : , nCurYOffset(0) // memorize nCurYOffset and not take it from EditEngine
1363 : , nMarkerPos(NoMarker)
1364 0 : , bErrorMarker(false)
1365 : {
1366 0 : setBackgroundColor(GetSettings().GetStyleSettings().GetFieldColor());
1367 0 : SetHelpId(HID_BASICIDE_BREAKPOINTWINDOW);
1368 0 : }
1369 :
1370 0 : BreakPointWindow::~BreakPointWindow()
1371 : {
1372 0 : }
1373 :
1374 :
1375 :
1376 0 : void BreakPointWindow::Paint( const Rectangle& )
1377 : {
1378 0 : if ( SyncYOffset() )
1379 0 : return;
1380 :
1381 0 : Size const aOutSz = GetOutputSize();
1382 0 : long const nLineHeight = GetTextHeight();
1383 :
1384 0 : Image const aBrk[2] = { GetImage(IMGID_BRKDISABLED), GetImage(IMGID_BRKENABLED) };
1385 0 : Size const aBmpSz = PixelToLogic(aBrk[1].GetSizePixel());
1386 : Point const aBmpOff(
1387 0 : (aOutSz.Width() - aBmpSz.Width()) / 2,
1388 0 : (nLineHeight - aBmpSz.Height()) / 2
1389 0 : );
1390 :
1391 0 : for (size_t i = 0, n = GetBreakPoints().size(); i < n; ++i)
1392 : {
1393 0 : BreakPoint& rBrk = *GetBreakPoints().at(i);
1394 0 : size_t const nLine = rBrk.nLine - 1;
1395 0 : size_t const nY = nLine*nLineHeight - nCurYOffset;
1396 0 : DrawImage(Point(0, nY) + aBmpOff, aBrk[rBrk.bEnabled]);
1397 : }
1398 0 : ShowMarker(true);
1399 : }
1400 :
1401 :
1402 :
1403 0 : void BreakPointWindow::DoScroll( long nHorzScroll, long nVertScroll )
1404 : {
1405 0 : nCurYOffset -= nVertScroll;
1406 0 : Window::Scroll( nHorzScroll, nVertScroll );
1407 0 : }
1408 :
1409 :
1410 :
1411 0 : void BreakPointWindow::SetMarkerPos( sal_uInt16 nLine, bool bError )
1412 : {
1413 0 : if ( SyncYOffset() )
1414 0 : Update();
1415 :
1416 0 : ShowMarker( false );
1417 0 : nMarkerPos = nLine;
1418 0 : bErrorMarker = bError;
1419 0 : ShowMarker( true );
1420 0 : }
1421 :
1422 0 : void BreakPointWindow::SetNoMarker ()
1423 : {
1424 0 : SetMarkerPos(NoMarker);
1425 0 : }
1426 :
1427 0 : void BreakPointWindow::ShowMarker( bool bShow )
1428 : {
1429 0 : if ( nMarkerPos == NoMarker )
1430 0 : return;
1431 :
1432 0 : Size const aOutSz = GetOutputSize();
1433 0 : long const nLineHeight = GetTextHeight();
1434 :
1435 0 : Image aMarker = GetImage(bErrorMarker ? IMGID_ERRORMARKER : IMGID_STEPMARKER);
1436 :
1437 0 : Size aMarkerSz( aMarker.GetSizePixel() );
1438 0 : aMarkerSz = PixelToLogic( aMarkerSz );
1439 0 : Point aMarkerOff( 0, 0 );
1440 0 : aMarkerOff.X() = ( aOutSz.Width() - aMarkerSz.Width() ) / 2;
1441 0 : aMarkerOff.Y() = ( nLineHeight - aMarkerSz.Height() ) / 2;
1442 :
1443 0 : sal_uLong nY = nMarkerPos*nLineHeight - nCurYOffset;
1444 0 : Point aPos( 0, nY );
1445 0 : aPos += aMarkerOff;
1446 0 : if ( bShow )
1447 0 : DrawImage( aPos, aMarker );
1448 : else
1449 0 : Invalidate( Rectangle( aPos, aMarkerSz ) );
1450 : }
1451 :
1452 :
1453 :
1454 :
1455 0 : BreakPoint* BreakPointWindow::FindBreakPoint( const Point& rMousePos )
1456 : {
1457 0 : size_t nLineHeight = GetTextHeight();
1458 0 : nLineHeight = nLineHeight > 0 ? nLineHeight : 1;
1459 0 : size_t nYPos = rMousePos.Y() + nCurYOffset;
1460 :
1461 0 : for ( size_t i = 0, n = GetBreakPoints().size(); i < n ; ++i )
1462 : {
1463 0 : BreakPoint* pBrk = GetBreakPoints().at( i );
1464 0 : size_t nLine = pBrk->nLine-1;
1465 0 : size_t nY = nLine*nLineHeight;
1466 0 : if ( ( nYPos > nY ) && ( nYPos < ( nY + nLineHeight ) ) )
1467 0 : return pBrk;
1468 : }
1469 0 : return 0;
1470 : }
1471 :
1472 0 : void BreakPointWindow::MouseButtonDown( const MouseEvent& rMEvt )
1473 : {
1474 0 : if ( rMEvt.GetClicks() == 2 )
1475 : {
1476 0 : Point aMousePos( PixelToLogic( rMEvt.GetPosPixel() ) );
1477 0 : long nLineHeight = GetTextHeight();
1478 0 : long nYPos = aMousePos.Y() + nCurYOffset;
1479 0 : long nLine = nYPos / nLineHeight + 1;
1480 0 : rModulWindow.ToggleBreakPoint( (sal_uLong)nLine );
1481 0 : Invalidate();
1482 : }
1483 0 : }
1484 :
1485 :
1486 :
1487 0 : void BreakPointWindow::Command( const CommandEvent& rCEvt )
1488 : {
1489 0 : if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
1490 : {
1491 0 : Point aPos( rCEvt.IsMouseEvent() ? rCEvt.GetMousePosPixel() : Point(1,1) );
1492 0 : Point aEventPos( PixelToLogic( aPos ) );
1493 0 : BreakPoint* pBrk = rCEvt.IsMouseEvent() ? FindBreakPoint( aEventPos ) : 0;
1494 0 : if ( pBrk )
1495 : {
1496 : // test if break point is enabled...
1497 0 : PopupMenu aBrkPropMenu( IDEResId( RID_POPUP_BRKPROPS ) );
1498 0 : aBrkPropMenu.CheckItem( RID_ACTIV, pBrk->bEnabled );
1499 0 : switch ( aBrkPropMenu.Execute( this, aPos ) )
1500 : {
1501 : case RID_ACTIV:
1502 : {
1503 0 : pBrk->bEnabled = !pBrk->bEnabled;
1504 0 : rModulWindow.UpdateBreakPoint( *pBrk );
1505 0 : Invalidate();
1506 : }
1507 0 : break;
1508 : case RID_BRKPROPS:
1509 : {
1510 0 : BreakPointDialog aBrkDlg( this, GetBreakPoints() );
1511 0 : aBrkDlg.SetCurrentBreakPoint( pBrk );
1512 0 : aBrkDlg.Execute();
1513 0 : Invalidate();
1514 : }
1515 0 : break;
1516 0 : }
1517 : }
1518 : else
1519 : {
1520 0 : PopupMenu aBrkListMenu( IDEResId( RID_POPUP_BRKDLG ) );
1521 0 : switch ( aBrkListMenu.Execute( this, aPos ) )
1522 : {
1523 : case RID_BRKDLG:
1524 : {
1525 0 : BreakPointDialog aBrkDlg( this, GetBreakPoints() );
1526 0 : aBrkDlg.Execute();
1527 0 : Invalidate();
1528 : }
1529 0 : break;
1530 0 : }
1531 : }
1532 : }
1533 0 : }
1534 :
1535 0 : bool BreakPointWindow::SyncYOffset()
1536 : {
1537 0 : TextView* pView = rModulWindow.GetEditView();
1538 0 : if ( pView )
1539 : {
1540 0 : long nViewYOffset = pView->GetStartDocPos().Y();
1541 0 : if ( nCurYOffset != nViewYOffset )
1542 : {
1543 0 : nCurYOffset = nViewYOffset;
1544 0 : Invalidate();
1545 0 : return true;
1546 : }
1547 : }
1548 0 : return false;
1549 : }
1550 :
1551 : // virtual
1552 0 : void BreakPointWindow::DataChanged(DataChangedEvent const & rDCEvt)
1553 : {
1554 0 : Window::DataChanged(rDCEvt);
1555 0 : if (rDCEvt.GetType() == DATACHANGED_SETTINGS
1556 0 : && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
1557 : {
1558 0 : Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
1559 0 : const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
1560 0 : if (!pOldSettings || aColor != pOldSettings->GetStyleSettings().GetFieldColor())
1561 : {
1562 0 : setBackgroundColor(aColor);
1563 0 : Invalidate();
1564 : }
1565 : }
1566 0 : }
1567 :
1568 0 : void BreakPointWindow::setBackgroundColor(Color aColor)
1569 : {
1570 0 : SetBackground(Wallpaper(aColor));
1571 0 : }
1572 :
1573 :
1574 :
1575 : // WatchWindow
1576 :
1577 :
1578 :
1579 : namespace
1580 : {
1581 : const sal_uInt16 ITEM_ID_VARIABLE = 1;
1582 : const sal_uInt16 ITEM_ID_VALUE = 2;
1583 : const sal_uInt16 ITEM_ID_TYPE = 3;
1584 : }
1585 :
1586 0 : WatchWindow::WatchWindow (Layout* pParent) :
1587 : DockingWindow(pParent),
1588 : aWatchStr( IDEResId( RID_STR_REMOVEWATCH ) ),
1589 : aXEdit( this, IDEResId( RID_EDT_WATCHEDIT ) ),
1590 : aRemoveWatchButton( this, IDEResId( RID_IMGBTN_REMOVEWATCH ) ),
1591 : aTreeListBox( this, WB_BORDER | WB_3DLOOK | WB_HASBUTTONS | WB_HASLINES | WB_HSCROLL | WB_TABSTOP
1592 : | WB_HASLINESATROOT | WB_HASBUTTONSATROOT ),
1593 0 : aHeaderBar( this, WB_BUTTONSTYLE | WB_BORDER )
1594 : {
1595 0 : aXEdit.SetAccessibleName(IDEResId(RID_STR_WATCHNAME).toString());
1596 0 : aTreeListBox.SetAccessibleName(IDEResId(RID_STR_WATCHNAME).toString());
1597 :
1598 0 : long nTextLen = GetTextWidth( aWatchStr ) + DWBORDER + 3;
1599 0 : aXEdit.SetPosPixel( Point( nTextLen, 3 ) );
1600 0 : aXEdit.SetAccHdl( LINK( this, WatchWindow, EditAccHdl ) );
1601 0 : aXEdit.GetAccelerator().InsertItem( 1, KeyCode( KEY_RETURN ) );
1602 0 : aXEdit.GetAccelerator().InsertItem( 2, KeyCode( KEY_ESCAPE ) );
1603 0 : aXEdit.Show();
1604 :
1605 0 : aRemoveWatchButton.Disable();
1606 0 : aRemoveWatchButton.SetClickHdl( LINK( this, WatchWindow, ButtonHdl ) );
1607 0 : aRemoveWatchButton.SetPosPixel( Point( nTextLen + aXEdit.GetSizePixel().Width() + 4, 2 ) );
1608 0 : Size aSz( aRemoveWatchButton.GetModeImage().GetSizePixel() );
1609 0 : aSz.Width() += 6;
1610 0 : aSz.Height() += 6;
1611 0 : aRemoveWatchButton.SetSizePixel( aSz );
1612 0 : aRemoveWatchButton.Show();
1613 :
1614 0 : long nRWBtnSize = aRemoveWatchButton.GetModeImage().GetSizePixel().Height() + 10;
1615 0 : nVirtToolBoxHeight = aXEdit.GetSizePixel().Height() + 7;
1616 :
1617 0 : if ( nRWBtnSize > nVirtToolBoxHeight )
1618 0 : nVirtToolBoxHeight = nRWBtnSize;
1619 :
1620 0 : nHeaderBarHeight = 16;
1621 :
1622 0 : aTreeListBox.SetHelpId(HID_BASICIDE_WATCHWINDOW_LIST);
1623 0 : aTreeListBox.EnableInplaceEditing(true);
1624 0 : aTreeListBox.SetSelectHdl( LINK( this, WatchWindow, TreeListHdl ) );
1625 0 : aTreeListBox.SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight + nHeaderBarHeight ) );
1626 0 : aTreeListBox.SetHighlightRange( 1, 5 );
1627 :
1628 0 : Point aPnt( DWBORDER, nVirtToolBoxHeight + 1 );
1629 0 : aHeaderBar.SetPosPixel( aPnt );
1630 0 : aHeaderBar.SetEndDragHdl( LINK( this, WatchWindow, implEndDragHdl ) );
1631 :
1632 0 : long nVarTabWidth = 220;
1633 0 : long nValueTabWidth = 100;
1634 0 : long nTypeTabWidth = 1250;
1635 0 : aHeaderBar.InsertItem( ITEM_ID_VARIABLE, IDEResId(RID_STR_WATCHVARIABLE).toString(), nVarTabWidth );
1636 0 : aHeaderBar.InsertItem( ITEM_ID_VALUE, IDEResId(RID_STR_WATCHVALUE).toString(), nValueTabWidth );
1637 0 : aHeaderBar.InsertItem( ITEM_ID_TYPE, IDEResId(RID_STR_WATCHTYPE).toString(), nTypeTabWidth );
1638 :
1639 : long tabs[ 4 ];
1640 0 : tabs[ 0 ] = 3; // two tabs
1641 0 : tabs[ 1 ] = 0;
1642 0 : tabs[ 2 ] = nVarTabWidth;
1643 0 : tabs[ 3 ] = nVarTabWidth + nValueTabWidth;
1644 0 : aTreeListBox.SvHeaderTabListBox::SetTabs( tabs, MAP_PIXEL );
1645 0 : aTreeListBox.InitHeaderBar( &aHeaderBar );
1646 :
1647 0 : aTreeListBox.SetNodeDefaultImages( );
1648 :
1649 0 : aHeaderBar.Show();
1650 :
1651 0 : aTreeListBox.Show();
1652 :
1653 0 : SetText(IDEResId(RID_STR_WATCHNAME).toString());
1654 :
1655 0 : SetHelpId( HID_BASICIDE_WATCHWINDOW );
1656 :
1657 : // make watch window keyboard accessible
1658 0 : GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1659 0 : }
1660 :
1661 :
1662 :
1663 0 : WatchWindow::~WatchWindow()
1664 : {
1665 0 : GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1666 0 : }
1667 :
1668 :
1669 :
1670 0 : void WatchWindow::Paint( const Rectangle& )
1671 : {
1672 0 : DrawText( Point( DWBORDER, 7 ), aWatchStr );
1673 0 : lcl_DrawIDEWindowFrame( this );
1674 0 : }
1675 :
1676 :
1677 :
1678 0 : void WatchWindow::Resize()
1679 : {
1680 0 : Size aSz = GetOutputSizePixel();
1681 0 : Size aBoxSz( aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER );
1682 :
1683 0 : if ( aBoxSz.Width() < 4 )
1684 0 : aBoxSz.Width() = 0;
1685 0 : if ( aBoxSz.Height() < 4 )
1686 0 : aBoxSz.Height() = 0;
1687 :
1688 0 : aBoxSz.Height() -= nHeaderBarHeight;
1689 0 : aTreeListBox.SetSizePixel( aBoxSz );
1690 0 : aTreeListBox.GetHScroll()->SetPageSize( aTreeListBox.GetHScroll()->GetVisibleSize() );
1691 :
1692 0 : aBoxSz.Height() = nHeaderBarHeight;
1693 0 : aHeaderBar.SetSizePixel( aBoxSz );
1694 :
1695 0 : Invalidate();
1696 0 : }
1697 :
1698 0 : struct WatchItem
1699 : {
1700 : OUString maName;
1701 : OUString maDisplayName;
1702 : SbxObjectRef mpObject;
1703 : std::vector<OUString> maMemberList;
1704 :
1705 : SbxDimArrayRef mpArray;
1706 : int nDimLevel; // 0 = Root
1707 : int nDimCount;
1708 : std::vector<short> vIndices;
1709 :
1710 : WatchItem* mpArrayParentItem;
1711 :
1712 0 : WatchItem (OUString const& rName):
1713 : maName(rName),
1714 : nDimLevel(0),
1715 : nDimCount(0),
1716 0 : mpArrayParentItem(0)
1717 0 : { }
1718 :
1719 0 : void clearWatchItem ()
1720 : {
1721 0 : maMemberList.clear();
1722 0 : }
1723 :
1724 : WatchItem* GetRootItem( void );
1725 : SbxDimArray* GetRootArray( void );
1726 : };
1727 :
1728 0 : WatchItem* WatchItem::GetRootItem( void )
1729 : {
1730 0 : WatchItem* pItem = mpArrayParentItem;
1731 0 : while( pItem )
1732 : {
1733 0 : if( pItem->mpArray.Is() )
1734 0 : break;
1735 0 : pItem = pItem->mpArrayParentItem;
1736 : }
1737 0 : return pItem;
1738 : }
1739 :
1740 0 : SbxDimArray* WatchItem::GetRootArray( void )
1741 : {
1742 0 : WatchItem* pRootItem = GetRootItem();
1743 0 : SbxDimArray* pRet = NULL;
1744 0 : if( pRootItem )
1745 0 : pRet = pRootItem->mpArray;
1746 0 : return pRet;
1747 : }
1748 :
1749 0 : void WatchWindow::AddWatch( const OUString& rVName )
1750 : {
1751 0 : OUString aVar, aIndex;
1752 0 : lcl_SeparateNameAndIndex( rVName, aVar, aIndex );
1753 0 : WatchItem* pWatchItem = new WatchItem(aVar);
1754 :
1755 0 : OUString aWatchStr_( aVar );
1756 0 : aWatchStr_ += "\t\t";
1757 0 : SvTreeListEntry* pNewEntry = aTreeListBox.InsertEntry( aWatchStr_, 0, true, TREELIST_APPEND );
1758 0 : pNewEntry->SetUserData( pWatchItem );
1759 :
1760 0 : aTreeListBox.Select(pNewEntry, true);
1761 0 : aTreeListBox.MakeVisible(pNewEntry);
1762 0 : aRemoveWatchButton.Enable();
1763 :
1764 0 : UpdateWatches();
1765 0 : }
1766 :
1767 0 : bool WatchWindow::RemoveSelectedWatch()
1768 : {
1769 0 : SvTreeListEntry* pEntry = aTreeListBox.GetCurEntry();
1770 0 : if ( pEntry )
1771 : {
1772 0 : aTreeListBox.GetModel()->Remove( pEntry );
1773 0 : pEntry = aTreeListBox.GetCurEntry();
1774 0 : if ( pEntry )
1775 0 : aXEdit.SetText( ((WatchItem*)pEntry->GetUserData())->maName );
1776 : else
1777 0 : aXEdit.SetText( OUString() );
1778 0 : if ( !aTreeListBox.GetEntryCount() )
1779 0 : aRemoveWatchButton.Disable();
1780 0 : return true;
1781 : }
1782 : else
1783 0 : return false;
1784 : }
1785 :
1786 :
1787 0 : IMPL_LINK_INLINE_START( WatchWindow, ButtonHdl, ImageButton *, pButton )
1788 : {
1789 0 : if (pButton == &aRemoveWatchButton)
1790 0 : if (SfxDispatcher* pDispatcher = GetDispatcher())
1791 0 : pDispatcher->Execute(SID_BASICIDE_REMOVEWATCH);
1792 0 : return 0;
1793 : }
1794 0 : IMPL_LINK_INLINE_END( WatchWindow, ButtonHdl, ImageButton *, pButton )
1795 :
1796 :
1797 :
1798 0 : IMPL_LINK_NOARG_INLINE_START(WatchWindow, TreeListHdl)
1799 : {
1800 0 : SvTreeListEntry* pCurEntry = aTreeListBox.GetCurEntry();
1801 0 : if ( pCurEntry && pCurEntry->GetUserData() )
1802 0 : aXEdit.SetText( ((WatchItem*)pCurEntry->GetUserData())->maName );
1803 :
1804 0 : return 0;
1805 : }
1806 0 : IMPL_LINK_NOARG_INLINE_END(WatchWindow, TreeListHdl)
1807 :
1808 :
1809 0 : IMPL_LINK_INLINE_START( WatchWindow, implEndDragHdl, HeaderBar *, pBar )
1810 : {
1811 : (void)pBar;
1812 :
1813 0 : const sal_Int32 TAB_WIDTH_MIN = 10;
1814 : sal_Int32 nMaxWidth =
1815 0 : aHeaderBar.GetSizePixel().getWidth() - 2 * TAB_WIDTH_MIN;
1816 :
1817 0 : sal_Int32 nVariableWith = aHeaderBar.GetItemSize( ITEM_ID_VARIABLE );
1818 0 : if( nVariableWith < TAB_WIDTH_MIN )
1819 0 : aHeaderBar.SetItemSize( ITEM_ID_VARIABLE, TAB_WIDTH_MIN );
1820 0 : else if( nVariableWith > nMaxWidth )
1821 0 : aHeaderBar.SetItemSize( ITEM_ID_VARIABLE, nMaxWidth );
1822 :
1823 0 : sal_Int32 nValueWith = aHeaderBar.GetItemSize( ITEM_ID_VALUE );
1824 0 : if( nValueWith < TAB_WIDTH_MIN )
1825 0 : aHeaderBar.SetItemSize( ITEM_ID_VALUE, TAB_WIDTH_MIN );
1826 0 : else if( nValueWith > nMaxWidth )
1827 0 : aHeaderBar.SetItemSize( ITEM_ID_VALUE, nMaxWidth );
1828 :
1829 0 : if (aHeaderBar.GetItemSize( ITEM_ID_TYPE ) < TAB_WIDTH_MIN)
1830 0 : aHeaderBar.SetItemSize( ITEM_ID_TYPE, TAB_WIDTH_MIN );
1831 :
1832 0 : sal_Int32 nPos = 0;
1833 0 : sal_uInt16 nTabs = aHeaderBar.GetItemCount();
1834 0 : for( sal_uInt16 i = 1 ; i < nTabs ; ++i )
1835 : {
1836 0 : nPos += aHeaderBar.GetItemSize( i );
1837 0 : aTreeListBox.SetTab( i, nPos, MAP_PIXEL );
1838 : }
1839 0 : return 0;
1840 : }
1841 0 : IMPL_LINK_INLINE_END( WatchWindow, implEndDragHdl, HeaderBar *, pBar )
1842 :
1843 :
1844 0 : IMPL_LINK( WatchWindow, EditAccHdl, Accelerator *, pAcc )
1845 : {
1846 0 : switch ( pAcc->GetCurKeyCode().GetCode() )
1847 : {
1848 : case KEY_RETURN:
1849 : {
1850 0 : OUString aCurText( aXEdit.GetText() );
1851 0 : if ( !aCurText.isEmpty() )
1852 : {
1853 0 : AddWatch( aCurText );
1854 0 : aXEdit.SetSelection( Selection( 0, 0xFFFF ) );
1855 0 : }
1856 : }
1857 0 : break;
1858 : case KEY_ESCAPE:
1859 : {
1860 0 : aXEdit.SetText( OUString() );
1861 : }
1862 0 : break;
1863 : }
1864 :
1865 0 : return 0;
1866 : }
1867 :
1868 0 : void WatchWindow::UpdateWatches( bool bBasicStopped )
1869 : {
1870 0 : aTreeListBox.UpdateWatches( bBasicStopped );
1871 0 : }
1872 :
1873 :
1874 :
1875 : // StackWindow
1876 :
1877 :
1878 :
1879 0 : StackWindow::StackWindow (Layout* pParent) :
1880 : DockingWindow(pParent),
1881 : aTreeListBox( this, WB_BORDER | WB_3DLOOK | WB_HSCROLL | WB_TABSTOP ),
1882 0 : aStackStr( IDEResId( RID_STR_STACK ) )
1883 : {
1884 0 : aTreeListBox.SetHelpId(HID_BASICIDE_STACKWINDOW_LIST);
1885 0 : aTreeListBox.SetAccessibleName(IDEResId(RID_STR_STACKNAME).toString());
1886 0 : aTreeListBox.SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight ) );
1887 0 : aTreeListBox.SetHighlightRange();
1888 0 : aTreeListBox.SetSelectionMode( NO_SELECTION );
1889 0 : aTreeListBox.InsertEntry( OUString(), 0, false, TREELIST_APPEND );
1890 0 : aTreeListBox.Show();
1891 :
1892 0 : SetText(IDEResId(RID_STR_STACKNAME).toString());
1893 :
1894 0 : SetHelpId( HID_BASICIDE_STACKWINDOW );
1895 :
1896 : // make stack window keyboard accessible
1897 0 : GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1898 0 : }
1899 :
1900 :
1901 :
1902 0 : StackWindow::~StackWindow()
1903 : {
1904 0 : GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1905 0 : }
1906 :
1907 :
1908 :
1909 0 : void StackWindow::Paint( const Rectangle& )
1910 : {
1911 0 : DrawText( Point( DWBORDER, 7 ), aStackStr );
1912 0 : lcl_DrawIDEWindowFrame( this );
1913 0 : }
1914 :
1915 :
1916 :
1917 0 : void StackWindow::Resize()
1918 : {
1919 0 : Size aSz = GetOutputSizePixel();
1920 0 : Size aBoxSz( aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER );
1921 :
1922 0 : if ( aBoxSz.Width() < 4 )
1923 0 : aBoxSz.Width() = 0;
1924 0 : if ( aBoxSz.Height() < 4 )
1925 0 : aBoxSz.Height() = 0;
1926 :
1927 0 : aTreeListBox.SetSizePixel( aBoxSz );
1928 :
1929 0 : Invalidate();
1930 0 : }
1931 :
1932 0 : void StackWindow::UpdateCalls()
1933 : {
1934 0 : aTreeListBox.SetUpdateMode(false);
1935 0 : aTreeListBox.Clear();
1936 :
1937 0 : if ( StarBASIC::IsRunning() )
1938 : {
1939 0 : SbxError eOld = SbxBase::GetError();
1940 0 : aTreeListBox.SetSelectionMode( SINGLE_SELECTION );
1941 :
1942 0 : sal_Int32 nScope = 0;
1943 0 : SbMethod* pMethod = StarBASIC::GetActiveMethod( nScope );
1944 0 : while ( pMethod )
1945 : {
1946 0 : OUString aEntry( OUString::number(nScope ));
1947 0 : if ( aEntry.getLength() < 2 )
1948 0 : aEntry = " " + aEntry;
1949 0 : aEntry += ": " + pMethod->GetName();
1950 0 : SbxArray* pParams = pMethod->GetParameters();
1951 0 : SbxInfo* pInfo = pMethod->GetInfo();
1952 0 : if ( pParams )
1953 : {
1954 0 : aEntry += "(";
1955 : // 0 is the sub's name...
1956 0 : for ( sal_uInt16 nParam = 1; nParam < pParams->Count(); nParam++ )
1957 : {
1958 0 : SbxVariable* pVar = pParams->Get( nParam );
1959 : DBG_ASSERT( pVar, "Parameter?!" );
1960 0 : if ( !pVar->GetName().isEmpty() )
1961 : {
1962 0 : aEntry += pVar->GetName();
1963 : }
1964 0 : else if ( pInfo )
1965 : {
1966 0 : const SbxParamInfo* pParam = pInfo->GetParam( nParam );
1967 0 : if ( pParam )
1968 : {
1969 0 : aEntry += pParam->aName;
1970 : }
1971 : }
1972 0 : aEntry += "=";
1973 0 : SbxDataType eType = pVar->GetType();
1974 0 : if( eType & SbxARRAY )
1975 : {
1976 0 : aEntry += "..." ;
1977 : }
1978 0 : else if( eType != SbxOBJECT )
1979 : {
1980 0 : aEntry += pVar->GetOUString();
1981 : }
1982 0 : if ( nParam < ( pParams->Count() - 1 ) )
1983 : {
1984 0 : aEntry += ", ";
1985 : }
1986 : }
1987 0 : aEntry += ")";
1988 : }
1989 0 : aTreeListBox.InsertEntry( aEntry, 0, false, TREELIST_APPEND );
1990 0 : nScope++;
1991 0 : pMethod = StarBASIC::GetActiveMethod( nScope );
1992 0 : }
1993 :
1994 0 : SbxBase::ResetError();
1995 0 : if( eOld != SbxERR_OK )
1996 0 : SbxBase::SetError( eOld );
1997 : }
1998 : else
1999 : {
2000 0 : aTreeListBox.SetSelectionMode( NO_SELECTION );
2001 0 : aTreeListBox.InsertEntry( OUString(), 0, false, TREELIST_APPEND );
2002 : }
2003 :
2004 0 : aTreeListBox.SetUpdateMode(true);
2005 0 : }
2006 :
2007 :
2008 :
2009 : // ComplexEditorWindow
2010 :
2011 :
2012 :
2013 0 : ComplexEditorWindow::ComplexEditorWindow( ModulWindow* pParent ) :
2014 : Window( pParent, WB_3DLOOK | WB_CLIPCHILDREN ),
2015 : aBrkWindow(this, pParent),
2016 : aLineNumberWindow(this, pParent),
2017 : aEdtWindow(this, pParent),
2018 0 : aEWVScrollBar( this, WB_VSCROLL | WB_DRAG )
2019 : {
2020 0 : aEdtWindow.Show();
2021 0 : aBrkWindow.Show();
2022 :
2023 0 : aEWVScrollBar.SetLineSize(nScrollLine);
2024 0 : aEWVScrollBar.SetPageSize(nScrollPage);
2025 0 : aEWVScrollBar.SetScrollHdl( LINK( this, ComplexEditorWindow, ScrollHdl ) );
2026 0 : aEWVScrollBar.Show();
2027 0 : }
2028 :
2029 0 : void ComplexEditorWindow::Resize()
2030 : {
2031 0 : Size aOutSz = GetOutputSizePixel();
2032 0 : Size aSz( aOutSz );
2033 0 : aSz.Width() -= 2*DWBORDER;
2034 0 : aSz.Height() -= 2*DWBORDER;
2035 0 : long nBrkWidth = 20;
2036 0 : long nSBWidth = aEWVScrollBar.GetSizePixel().Width();
2037 :
2038 0 : Size aBrkSz(nBrkWidth, aSz.Height());
2039 :
2040 0 : Size aLnSz(aLineNumberWindow.GetWidth(), aSz.Height());
2041 :
2042 0 : if (aLineNumberWindow.IsVisible())
2043 : {
2044 0 : aBrkWindow.SetPosSizePixel( Point( DWBORDER, DWBORDER ), aBrkSz );
2045 0 : aLineNumberWindow.SetPosSizePixel(Point(DWBORDER + aBrkSz.Width() - 1, DWBORDER), aLnSz);
2046 0 : Size aEWSz(aSz.Width() - nBrkWidth - aLineNumberWindow.GetWidth() - nSBWidth + 2, aSz.Height());
2047 0 : aEdtWindow.SetPosSizePixel( Point( DWBORDER + aBrkSz.Width() + aLnSz.Width() - 1, DWBORDER ), aEWSz );
2048 : }
2049 : else
2050 : {
2051 0 : aBrkWindow.SetPosSizePixel( Point( DWBORDER, DWBORDER ), aBrkSz );
2052 0 : Size aEWSz(aSz.Width() - nBrkWidth - nSBWidth + 2, aSz.Height());
2053 0 : aEdtWindow.SetPosSizePixel(Point(DWBORDER + aBrkSz.Width() - 1, DWBORDER), aEWSz);
2054 : }
2055 :
2056 0 : aEWVScrollBar.SetPosSizePixel( Point( aOutSz.Width() - DWBORDER - nSBWidth, DWBORDER ), Size( nSBWidth, aSz.Height() ) );
2057 0 : }
2058 :
2059 0 : IMPL_LINK( ComplexEditorWindow, ScrollHdl, ScrollBar *, pCurScrollBar )
2060 : {
2061 0 : if ( aEdtWindow.GetEditView() )
2062 : {
2063 : DBG_ASSERT( pCurScrollBar == &aEWVScrollBar, "Wer scrollt hier ?" );
2064 0 : long nDiff = aEdtWindow.GetEditView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
2065 0 : aEdtWindow.GetEditView()->Scroll( 0, nDiff );
2066 0 : aBrkWindow.DoScroll( 0, nDiff );
2067 0 : aLineNumberWindow.DoScroll(0, nDiff);
2068 0 : aEdtWindow.GetEditView()->ShowCursor(false, true);
2069 0 : pCurScrollBar->SetThumbPos( aEdtWindow.GetEditView()->GetStartDocPos().Y() );
2070 : }
2071 :
2072 0 : return 0;
2073 : }
2074 :
2075 0 : void ComplexEditorWindow::DataChanged(DataChangedEvent const & rDCEvt)
2076 : {
2077 0 : Window::DataChanged(rDCEvt);
2078 0 : if (rDCEvt.GetType() == DATACHANGED_SETTINGS
2079 0 : && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
2080 : {
2081 0 : Color aColor(GetSettings().GetStyleSettings().GetFaceColor());
2082 0 : const AllSettings* pOldSettings = rDCEvt.GetOldSettings();
2083 0 : if (!pOldSettings || aColor != pOldSettings->GetStyleSettings().GetFaceColor())
2084 : {
2085 0 : SetBackground(Wallpaper(aColor));
2086 0 : Invalidate();
2087 : }
2088 : }
2089 0 : }
2090 :
2091 0 : void ComplexEditorWindow::SetLineNumberDisplay(bool b)
2092 : {
2093 0 : aLineNumberWindow.Show(b);
2094 0 : Resize();
2095 0 : }
2096 :
2097 : uno::Reference< awt::XWindowPeer >
2098 0 : EditorWindow::GetComponentInterface(sal_Bool bCreate)
2099 : {
2100 : uno::Reference< awt::XWindowPeer > xPeer(
2101 0 : Window::GetComponentInterface(false));
2102 0 : if (!xPeer.is() && bCreate)
2103 : {
2104 : // Make sure edit engine and view are available:
2105 0 : if (!pEditEngine)
2106 0 : CreateEditEngine();
2107 :
2108 0 : xPeer = svt::createTextWindowPeer(*GetEditView());
2109 0 : SetComponentInterface(xPeer);
2110 : }
2111 0 : return xPeer;
2112 : }
2113 :
2114 :
2115 :
2116 : // WatchTreeListBox
2117 :
2118 :
2119 :
2120 0 : WatchTreeListBox::WatchTreeListBox( Window* pParent, WinBits nWinBits )
2121 0 : : SvHeaderTabListBox( pParent, nWinBits )
2122 0 : {}
2123 :
2124 0 : WatchTreeListBox::~WatchTreeListBox()
2125 : {
2126 : // Destroy user data
2127 0 : SvTreeListEntry* pEntry = First();
2128 0 : while ( pEntry )
2129 : {
2130 0 : delete (WatchItem*)pEntry->GetUserData();
2131 0 : pEntry = Next( pEntry );
2132 : }
2133 0 : }
2134 :
2135 0 : void WatchTreeListBox::SetTabs()
2136 : {
2137 0 : SvHeaderTabListBox::SetTabs();
2138 0 : sal_uInt16 nTabCount_ = aTabs.size();
2139 0 : for( sal_uInt16 i = 0 ; i < nTabCount_ ; i++ )
2140 : {
2141 0 : SvLBoxTab* pTab = aTabs[i];
2142 0 : if( i == 2 )
2143 0 : pTab->nFlags |= SV_LBOXTAB_EDITABLE;
2144 : else
2145 0 : pTab->nFlags &= ~SV_LBOXTAB_EDITABLE;
2146 : }
2147 0 : }
2148 :
2149 0 : void WatchTreeListBox::RequestingChildren( SvTreeListEntry * pParent )
2150 : {
2151 0 : if( !StarBASIC::IsRunning() )
2152 0 : return;
2153 :
2154 0 : if( GetChildCount( pParent ) > 0 )
2155 0 : return;
2156 :
2157 0 : SvTreeListEntry* pEntry = pParent;
2158 0 : WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
2159 :
2160 0 : SbxDimArray* pArray = pItem->mpArray;
2161 0 : SbxDimArray* pRootArray = pItem->GetRootArray();
2162 0 : bool bArrayIsRootArray = false;
2163 0 : if( !pArray && pRootArray )
2164 : {
2165 0 : pArray = pRootArray;
2166 0 : bArrayIsRootArray = true;
2167 : }
2168 :
2169 0 : SbxObject* pObj = pItem->mpObject;
2170 0 : if( pObj )
2171 : {
2172 0 : createAllObjectProperties( pObj );
2173 0 : SbxArray* pProps = pObj->GetProperties();
2174 0 : sal_uInt16 nPropCount = pProps->Count();
2175 0 : pItem->maMemberList.reserve(nPropCount);
2176 :
2177 0 : for( sal_uInt16 i = 0 ; i < nPropCount - 3 ; i++ )
2178 : {
2179 0 : SbxVariable* pVar = pProps->Get( i );
2180 :
2181 0 : pItem->maMemberList.push_back(pVar->GetName());
2182 0 : OUString const& rName = pItem->maMemberList.back();
2183 0 : SvTreeListEntry* pChildEntry = SvTreeListBox::InsertEntry( rName, pEntry );
2184 0 : pChildEntry->SetUserData(new WatchItem(rName));
2185 : }
2186 0 : if( nPropCount > 0 )
2187 : {
2188 0 : UpdateWatches();
2189 : }
2190 : }
2191 0 : else if( pArray )
2192 : {
2193 0 : sal_uInt16 nElementCount = 0;
2194 :
2195 : // Loop through indices of current level
2196 0 : int nParentLevel = bArrayIsRootArray ? pItem->nDimLevel : 0;
2197 0 : int nThisLevel = nParentLevel + 1;
2198 : sal_Int32 nMin, nMax;
2199 0 : pArray->GetDim32( nThisLevel, nMin, nMax );
2200 0 : for( sal_Int32 i = nMin ; i <= nMax ; i++ )
2201 : {
2202 0 : WatchItem* pChildItem = new WatchItem(pItem->maName);
2203 :
2204 : // Copy data and create name
2205 :
2206 0 : OUString aIndexStr = "(";
2207 0 : pChildItem->mpArrayParentItem = pItem;
2208 0 : pChildItem->nDimLevel = nThisLevel;
2209 0 : pChildItem->nDimCount = pItem->nDimCount;
2210 0 : pChildItem->vIndices.resize(pChildItem->nDimCount);
2211 : sal_Int32 j;
2212 0 : for( j = 0 ; j < nParentLevel ; j++ )
2213 : {
2214 0 : short n = pChildItem->vIndices[j] = pItem->vIndices[j];
2215 0 : aIndexStr += OUString::number( n ) + ",";
2216 : }
2217 0 : pChildItem->vIndices[nParentLevel] = sal::static_int_cast<short>( i );
2218 0 : aIndexStr += OUString::number( i ) + ")";
2219 :
2220 0 : OUString aDisplayName;
2221 0 : WatchItem* pArrayRootItem = pChildItem->GetRootItem();
2222 0 : if( pArrayRootItem && pArrayRootItem->mpArrayParentItem )
2223 0 : aDisplayName = pItem->maDisplayName;
2224 : else
2225 0 : aDisplayName = pItem->maName;
2226 0 : aDisplayName += aIndexStr;
2227 0 : pChildItem->maDisplayName = aDisplayName;
2228 :
2229 0 : SvTreeListEntry* pChildEntry = SvTreeListBox::InsertEntry( aDisplayName, pEntry );
2230 0 : nElementCount++;
2231 0 : pChildEntry->SetUserData( pChildItem );
2232 0 : }
2233 0 : if( nElementCount > 0 )
2234 : {
2235 0 : UpdateWatches();
2236 : }
2237 : }
2238 : }
2239 :
2240 0 : SbxBase* WatchTreeListBox::ImplGetSBXForEntry( SvTreeListEntry* pEntry, bool& rbArrayElement )
2241 : {
2242 0 : SbxBase* pSBX = NULL;
2243 0 : rbArrayElement = false;
2244 :
2245 0 : WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
2246 0 : OUString aVName( pItem->maName );
2247 :
2248 0 : SvTreeListEntry* pParentEntry = GetParent( pEntry );
2249 0 : WatchItem* pParentItem = pParentEntry ? (WatchItem*)pParentEntry->GetUserData() : NULL;
2250 0 : if( pParentItem )
2251 : {
2252 0 : SbxObject* pObj = pParentItem->mpObject;
2253 : SbxDimArray* pArray;
2254 0 : if( pObj )
2255 : {
2256 0 : pSBX = pObj->Find( aVName, SbxCLASS_DONTCARE );
2257 0 : if (SbxVariable const* pVar = IsSbxVariable(pSBX))
2258 : {
2259 : // Force getting value
2260 0 : SbxValues aRes;
2261 0 : aRes.eType = SbxVOID;
2262 0 : pVar->Get( aRes );
2263 : }
2264 : }
2265 : // Array?
2266 0 : else if( (pArray = pItem->GetRootArray()) != NULL )
2267 : {
2268 0 : rbArrayElement = true;
2269 0 : if( pParentItem->nDimLevel + 1 == pParentItem->nDimCount )
2270 0 : pSBX = pArray->Get(pItem->vIndices.empty() ? 0 : &*pItem->vIndices.begin());
2271 : }
2272 : }
2273 : else
2274 : {
2275 0 : pSBX = StarBASIC::FindSBXInCurrentScope( aVName );
2276 : }
2277 0 : return pSBX;
2278 : }
2279 :
2280 0 : bool WatchTreeListBox::EditingEntry( SvTreeListEntry* pEntry, Selection& )
2281 : {
2282 0 : WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
2283 :
2284 0 : bool bEdit = false;
2285 0 : if ( StarBASIC::IsRunning() && StarBASIC::GetActiveMethod() && !SbxBase::IsError() )
2286 : {
2287 : // No out of scope entries
2288 : bool bArrayElement;
2289 0 : SbxBase* pSbx = ImplGetSBXForEntry( pEntry, bArrayElement );
2290 0 : if (IsSbxVariable(pSbx) || bArrayElement)
2291 : {
2292 : // Accept no objects and only end nodes of arrays for editing
2293 0 : if( !pItem->mpObject && (pItem->mpArray == NULL || pItem->nDimLevel == pItem->nDimCount) )
2294 : {
2295 0 : aEditingRes = SvHeaderTabListBox::GetEntryText( pEntry, ITEM_ID_VALUE-1 );
2296 0 : aEditingRes = comphelper::string::strip(aEditingRes, ' ');
2297 0 : bEdit = true;
2298 : }
2299 : }
2300 : }
2301 :
2302 0 : return bEdit;
2303 : }
2304 :
2305 0 : bool WatchTreeListBox::EditedEntry( SvTreeListEntry* pEntry, const OUString& rNewText )
2306 : {
2307 0 : OUString aResult = comphelper::string::strip(rNewText, ' ');
2308 :
2309 0 : sal_uInt16 nResultLen = aResult.getLength();
2310 0 : sal_Unicode cFirst = aResult[0];
2311 0 : sal_Unicode cLast = aResult[ nResultLen - 1 ];
2312 0 : if( cFirst == '\"' && cLast == '\"' )
2313 0 : aResult = aResult.copy( 1, nResultLen - 2 );
2314 :
2315 0 : return aResult != aEditingRes && ImplBasicEntryEdited(pEntry, aResult);
2316 : }
2317 :
2318 0 : bool WatchTreeListBox::ImplBasicEntryEdited( SvTreeListEntry* pEntry, const OUString& rResult )
2319 : {
2320 : bool bArrayElement;
2321 0 : SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
2322 :
2323 0 : if (SbxVariable* pVar = IsSbxVariable(pSBX))
2324 : {
2325 0 : SbxDataType eType = pVar->GetType();
2326 0 : if ( (sal_uInt8)eType != (sal_uInt8)SbxOBJECT
2327 0 : && ( eType & SbxARRAY ) == 0 )
2328 : {
2329 : // If the type is variable, the conversion of the SBX does not matter,
2330 : // else the string is converted.
2331 0 : pVar->PutStringExt( rResult );
2332 : }
2333 : }
2334 :
2335 0 : if ( SbxBase::IsError() )
2336 : {
2337 0 : SbxBase::ResetError();
2338 : }
2339 :
2340 0 : UpdateWatches();
2341 :
2342 : // The text should never be taken/copied 1:1,
2343 : // as the UpdateWatches will be lost
2344 0 : return false;
2345 : }
2346 :
2347 :
2348 : namespace
2349 : {
2350 :
2351 0 : void implCollapseModifiedObjectEntry( SvTreeListEntry* pParent, WatchTreeListBox* pThis )
2352 : {
2353 0 : pThis->Collapse( pParent );
2354 :
2355 0 : SvTreeList* pModel = pThis->GetModel();
2356 : SvTreeListEntry* pDeleteEntry;
2357 0 : while( (pDeleteEntry = pThis->SvTreeListBox::GetEntry( pParent, 0 )) != NULL )
2358 : {
2359 0 : implCollapseModifiedObjectEntry( pDeleteEntry, pThis );
2360 :
2361 0 : delete (WatchItem*)pDeleteEntry->GetUserData();
2362 0 : pModel->Remove( pDeleteEntry );
2363 : }
2364 0 : }
2365 :
2366 0 : OUString implCreateTypeStringForDimArray( WatchItem* pItem, SbxDataType eType )
2367 : {
2368 0 : OUString aRetStr = getBasicTypeName( eType );
2369 :
2370 0 : SbxDimArray* pArray = pItem->mpArray;
2371 0 : if( !pArray )
2372 0 : pArray = pItem->GetRootArray();
2373 0 : if( pArray )
2374 : {
2375 0 : int nDimLevel = pItem->nDimLevel;
2376 0 : int nDims = pItem->nDimCount;
2377 0 : if( nDimLevel < nDims )
2378 : {
2379 0 : aRetStr += "(";
2380 0 : for( int i = nDimLevel ; i < nDims ; i++ )
2381 : {
2382 : short nMin, nMax;
2383 0 : pArray->GetDim( sal::static_int_cast<short>( i+1 ), nMin, nMax );
2384 0 : aRetStr += OUString::number(nMin) + " to " + OUString::number(nMax);
2385 0 : if( i < nDims - 1 )
2386 0 : aRetStr += ", ";
2387 : }
2388 0 : aRetStr += ")";
2389 : }
2390 : }
2391 0 : return aRetStr;
2392 : }
2393 :
2394 0 : void implEnableChildren( SvTreeListEntry* pEntry, bool bEnable )
2395 : {
2396 0 : if( bEnable )
2397 : {
2398 : pEntry->SetFlags(
2399 0 : (pEntry->GetFlags() &
2400 : ~(SV_ENTRYFLAG_NO_NODEBMP | SV_ENTRYFLAG_HAD_CHILDREN))
2401 0 : | SV_ENTRYFLAG_CHILDREN_ON_DEMAND );
2402 : }
2403 : else
2404 : {
2405 : pEntry->SetFlags(
2406 0 : (pEntry->GetFlags() & ~(SV_ENTRYFLAG_CHILDREN_ON_DEMAND)) );
2407 : }
2408 0 : }
2409 :
2410 : } // namespace
2411 :
2412 0 : void WatchTreeListBox::UpdateWatches( bool bBasicStopped )
2413 : {
2414 0 : SbMethod* pCurMethod = StarBASIC::GetActiveMethod();
2415 :
2416 0 : SbxError eOld = SbxBase::GetError();
2417 0 : setBasicWatchMode( true );
2418 :
2419 0 : SvTreeListEntry* pEntry = First();
2420 0 : while ( pEntry )
2421 : {
2422 0 : WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
2423 : DBG_ASSERT( !pItem->maName.isEmpty(), "Var? - Must not be empty!" );
2424 0 : OUString aWatchStr;
2425 0 : OUString aTypeStr;
2426 0 : if ( pCurMethod )
2427 : {
2428 : bool bArrayElement;
2429 0 : SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
2430 :
2431 : // Array? If no end node create type string
2432 0 : if( bArrayElement && pItem->nDimLevel < pItem->nDimCount )
2433 : {
2434 0 : SbxDimArray* pRootArray = pItem->GetRootArray();
2435 0 : SbxDataType eType = pRootArray->GetType();
2436 0 : aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
2437 0 : implEnableChildren( pEntry, true );
2438 : }
2439 :
2440 0 : bool bCollapse = false;
2441 0 : if (SbxVariable const* pVar = IsSbxVariable(pSBX))
2442 : {
2443 : // extra treatment of arrays
2444 0 : SbxDataType eType = pVar->GetType();
2445 0 : if ( eType & SbxARRAY )
2446 : {
2447 : // consider multidimensinal arrays!
2448 0 : if (SbxDimArray* pNewArray = dynamic_cast<SbxDimArray*>(pVar->GetObject()))
2449 : {
2450 0 : SbxDimArray* pOldArray = pItem->mpArray;
2451 :
2452 0 : bool bArrayChanged = false;
2453 0 : if( pNewArray != NULL && pOldArray != NULL )
2454 : {
2455 : // Compare Array dimensions to see if array has changed
2456 : // Can be a copy, so comparing pointers does not work
2457 0 : sal_uInt16 nOldDims = pOldArray->GetDims();
2458 0 : sal_uInt16 nNewDims = pNewArray->GetDims();
2459 0 : if( nOldDims != nNewDims )
2460 : {
2461 0 : bArrayChanged = true;
2462 : }
2463 : else
2464 : {
2465 0 : for( int i = 0 ; i < nOldDims ; i++ )
2466 : {
2467 : short nOldMin, nOldMax;
2468 : short nNewMin, nNewMax;
2469 :
2470 0 : pOldArray->GetDim( sal::static_int_cast<short>( i+1 ), nOldMin, nOldMax );
2471 0 : pNewArray->GetDim( sal::static_int_cast<short>( i+1 ), nNewMin, nNewMax );
2472 0 : if( nOldMin != nNewMin || nOldMax != nNewMax )
2473 : {
2474 0 : bArrayChanged = true;
2475 0 : break;
2476 : }
2477 : }
2478 0 : }
2479 : }
2480 0 : else if( pNewArray == NULL || pOldArray == NULL )
2481 : {
2482 0 : bArrayChanged = true;
2483 : }
2484 0 : if( pNewArray )
2485 : {
2486 0 : implEnableChildren( pEntry, true );
2487 : }
2488 : // #i37227 Clear always and replace array
2489 0 : if( pNewArray != pOldArray )
2490 : {
2491 0 : pItem->clearWatchItem();
2492 0 : if( pNewArray )
2493 : {
2494 0 : implEnableChildren( pEntry, true );
2495 :
2496 0 : pItem->mpArray = pNewArray;
2497 0 : sal_uInt16 nDims = pNewArray->GetDims();
2498 0 : pItem->nDimLevel = 0;
2499 0 : pItem->nDimCount = nDims;
2500 : }
2501 : }
2502 0 : if( bArrayChanged && pOldArray != NULL )
2503 : {
2504 0 : bCollapse = true;
2505 : }
2506 0 : aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
2507 : }
2508 : else
2509 : {
2510 0 : aWatchStr += "<?>";
2511 : }
2512 : }
2513 0 : else if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
2514 : {
2515 0 : if (SbxObject* pObj = dynamic_cast<SbxObject*>(pVar->GetObject()))
2516 : {
2517 : // Check if member list has changed
2518 0 : bool bObjChanged = false;
2519 0 : if (pItem->mpObject && !pItem->maMemberList.empty())
2520 : {
2521 0 : SbxArray* pProps = pObj->GetProperties();
2522 0 : sal_uInt16 nPropCount = pProps->Count();
2523 0 : for( sal_uInt16 i = 0 ; i < nPropCount - 3 ; i++ )
2524 : {
2525 0 : SbxVariable* pVar_ = pProps->Get( i );
2526 0 : OUString aName( pVar_->GetName() );
2527 0 : if( pItem->maMemberList[i] != aName )
2528 : {
2529 0 : bObjChanged = true;
2530 0 : break;
2531 : }
2532 0 : }
2533 0 : if( bObjChanged )
2534 : {
2535 0 : bCollapse = true;
2536 : }
2537 : }
2538 :
2539 0 : pItem->mpObject = pObj;
2540 0 : implEnableChildren( pEntry, true );
2541 0 : aTypeStr = getBasicObjectTypeName( pObj );
2542 : }
2543 : else
2544 : {
2545 0 : aWatchStr = "Null";
2546 0 : if( pItem->mpObject != NULL )
2547 : {
2548 0 : bCollapse = true;
2549 0 : pItem->clearWatchItem();
2550 :
2551 0 : implEnableChildren( pEntry, false );
2552 : }
2553 : }
2554 : }
2555 : else
2556 : {
2557 0 : if( pItem->mpObject != NULL )
2558 : {
2559 0 : bCollapse = true;
2560 0 : pItem->clearWatchItem();
2561 :
2562 0 : implEnableChildren( pEntry, false );
2563 : }
2564 :
2565 0 : bool bString = ((sal_uInt8)eType == (sal_uInt8)SbxSTRING);
2566 0 : OUString aStrStr( "\"" );
2567 0 : if( bString )
2568 : {
2569 0 : aWatchStr += aStrStr;
2570 : }
2571 0 : aWatchStr += pVar->GetOUString();
2572 0 : if( bString )
2573 : {
2574 0 : aWatchStr += aStrStr;
2575 0 : }
2576 : }
2577 0 : if( aTypeStr.isEmpty() )
2578 : {
2579 0 : if( !pVar->IsFixed() )
2580 : {
2581 0 : aTypeStr = "Variant/";
2582 : }
2583 0 : aTypeStr += getBasicTypeName( pVar->GetType() );
2584 : }
2585 : }
2586 0 : else if( !bArrayElement )
2587 : {
2588 0 : aWatchStr += "<Out of Scope>";
2589 : }
2590 :
2591 0 : if( bCollapse )
2592 : {
2593 0 : implCollapseModifiedObjectEntry( pEntry, this );
2594 : }
2595 :
2596 : }
2597 0 : else if( bBasicStopped )
2598 : {
2599 0 : if( pItem->mpObject || pItem->mpArray )
2600 : {
2601 0 : implCollapseModifiedObjectEntry( pEntry, this );
2602 0 : pItem->mpObject = NULL;
2603 : }
2604 : }
2605 :
2606 0 : SvHeaderTabListBox::SetEntryText( aWatchStr, pEntry, ITEM_ID_VALUE-1 );
2607 0 : SvHeaderTabListBox::SetEntryText( aTypeStr, pEntry, ITEM_ID_TYPE-1 );
2608 :
2609 0 : pEntry = Next( pEntry );
2610 0 : }
2611 :
2612 : // Force redraw
2613 0 : Invalidate();
2614 :
2615 0 : SbxBase::ResetError();
2616 0 : if( eOld != SbxERR_OK )
2617 0 : SbxBase::SetError( eOld );
2618 0 : setBasicWatchMode( false );
2619 0 : }
2620 :
2621 0 : CodeCompleteListBox::CodeCompleteListBox( CodeCompleteWindow* pPar )
2622 : : ListBox(pPar, WB_SORT | WB_BORDER ),
2623 0 : pCodeCompleteWindow( pPar )
2624 : {
2625 0 : SetDoubleClickHdl(LINK(this, CodeCompleteListBox, ImplDoubleClickHdl));
2626 0 : SetSelectHdl(LINK(this, CodeCompleteListBox, ImplSelectHdl));
2627 0 : }
2628 :
2629 0 : IMPL_LINK_NOARG(CodeCompleteListBox, ImplDoubleClickHdl)
2630 : {
2631 0 : InsertSelectedEntry();
2632 0 : return 0;
2633 : }
2634 :
2635 0 : IMPL_LINK_NOARG(CodeCompleteListBox, ImplSelectHdl)
2636 : {//give back the focus to the parent
2637 0 : pCodeCompleteWindow->pParent->GrabFocus();
2638 0 : return 0;
2639 : }
2640 :
2641 0 : ExtTextView* CodeCompleteListBox::GetParentEditView()
2642 : {
2643 0 : return pCodeCompleteWindow->pParent->GetEditView();
2644 : }
2645 :
2646 0 : void CodeCompleteListBox::InsertSelectedEntry()
2647 : {
2648 0 : if( !aFuncBuffer.toString().isEmpty() )
2649 : {
2650 : // if the user typed in something: remove, and insert
2651 0 : GetParentEditView()->SetSelection( pCodeCompleteWindow->pParent->GetLastHighlightPortionTextSelection() );
2652 0 : GetParentEditView()->DeleteSelected();
2653 :
2654 0 : if( !((OUString) GetEntry( GetSelectEntryPos() )).isEmpty() )
2655 : {//if the user selected something
2656 0 : GetParentEditView()->InsertText( (OUString) GetEntry(GetSelectEntryPos()), false );
2657 : }
2658 : }
2659 : else
2660 : {
2661 0 : if( !((OUString) GetEntry( GetSelectEntryPos() )).isEmpty() )
2662 : {//if the user selected something
2663 0 : GetParentEditView()->InsertText( (OUString) GetEntry(GetSelectEntryPos()), false );
2664 : }
2665 : }
2666 0 : HideAndRestoreFocus();
2667 0 : }
2668 :
2669 0 : void CodeCompleteListBox::SetMatchingEntries()
2670 : {
2671 0 : for(sal_uInt16 i=0; i< GetEntryCount(); ++i)
2672 : {
2673 0 : OUString sEntry = (OUString) GetEntry(i);
2674 0 : if( sEntry.startsWithIgnoreAsciiCase( aFuncBuffer.toString() ) )
2675 : {
2676 0 : SelectEntry(sEntry);
2677 0 : break;
2678 : }
2679 0 : }
2680 0 : }
2681 :
2682 0 : void CodeCompleteListBox::KeyInput( const KeyEvent& rKeyEvt )
2683 : {
2684 0 : sal_Unicode aChar = rKeyEvt.GetKeyCode().GetCode();
2685 0 : if( (( aChar >= KEY_A ) && ( aChar <= KEY_Z ))
2686 0 : || ((aChar >= KEY_0) && (aChar <= KEY_9)) )
2687 : {
2688 0 : aFuncBuffer.append(rKeyEvt.GetCharCode());
2689 0 : SetMatchingEntries();
2690 : }
2691 : else
2692 : {
2693 0 : switch( aChar )
2694 : {
2695 : case KEY_ESCAPE: // hide, do nothing
2696 0 : HideAndRestoreFocus();
2697 0 : break;
2698 : case KEY_RIGHT:
2699 : {
2700 0 : TextSelection aTextSelection( GetParentEditView()->GetSelection() );
2701 0 : if( aTextSelection.GetEnd().GetPara() != pCodeCompleteWindow->GetTextSelection().GetEnd().GetPara()-1 )
2702 : {
2703 0 : HideAndRestoreFocus();
2704 : }
2705 0 : break;
2706 : }
2707 : case KEY_LEFT:
2708 : {
2709 0 : TextSelection aTextSelection( GetParentEditView()->GetSelection() );
2710 0 : if( aTextSelection.GetStart().GetIndex()-1 < pCodeCompleteWindow->GetTextSelection().GetStart().GetIndex() )
2711 : {//leave the cursor where it is
2712 0 : HideAndRestoreFocus();
2713 : }
2714 0 : break;
2715 : }
2716 : case KEY_TAB:
2717 : {
2718 0 : TextSelection aTextSelection = pCodeCompleteWindow->pParent->GetLastHighlightPortionTextSelection();
2719 0 : OUString sTypedText = pCodeCompleteWindow->pParent->GetEditEngine()->GetText(aTextSelection);
2720 0 : if( !aFuncBuffer.isEmpty() )
2721 : {
2722 0 : sal_Int32 nInd = GetSelectEntryPos();
2723 0 : if( nInd != LISTBOX_ENTRY_NOTFOUND )
2724 : {//if there is something selected
2725 0 : bool bFound = false;
2726 0 : if( nInd == GetEntryCount() )
2727 0 : nInd = 0;
2728 0 : for( sal_Int32 i = nInd; i != GetEntryCount(); ++i )
2729 : {
2730 0 : OUString sEntry = (OUString) GetEntry(i);
2731 0 : if( sEntry.startsWithIgnoreAsciiCase( aFuncBuffer.toString() )
2732 0 : && (aFuncBuffer.toString() != sTypedText) && (i != nInd) )
2733 : {
2734 0 : SelectEntry( sEntry );
2735 0 : bFound = true;
2736 0 : break;
2737 : }
2738 0 : }
2739 0 : if( !bFound )
2740 0 : SetMatchingEntries();
2741 :
2742 0 : GetParentEditView()->SetSelection( aTextSelection );
2743 0 : GetParentEditView()->DeleteSelected();
2744 0 : GetParentEditView()->InsertText( GetSelectEntry(), false );
2745 : }
2746 : }
2747 0 : break;
2748 : }
2749 : case KEY_SPACE:
2750 0 : HideAndRestoreFocus();
2751 0 : break;
2752 : case KEY_BACKSPACE: case KEY_DELETE:
2753 0 : if( !aFuncBuffer.toString().isEmpty() )
2754 : {
2755 : //if there was something inserted by tab: add it to aFuncBuffer
2756 0 : TextSelection aSel( GetParentEditView()->GetSelection() );
2757 0 : TextPaM aEnd( GetParentEditView()->CursorEndOfLine(pCodeCompleteWindow->GetTextSelection().GetEnd()) );
2758 0 : GetParentEditView()->SetSelection(TextSelection(pCodeCompleteWindow->GetTextSelection().GetStart(), aEnd ) );
2759 0 : OUString aTabInsertedStr( ((OUString)GetParentEditView()->GetSelected()) );
2760 0 : GetParentEditView()->SetSelection( aSel );
2761 :
2762 0 : if( !aTabInsertedStr.isEmpty() && aTabInsertedStr != aFuncBuffer.toString() )
2763 : {
2764 0 : aFuncBuffer.makeStringAndClear();
2765 0 : aFuncBuffer = aFuncBuffer.append(aTabInsertedStr);
2766 : }
2767 0 : aFuncBuffer = aFuncBuffer.remove(aFuncBuffer.getLength()-1, 1);
2768 0 : SetMatchingEntries();
2769 : }
2770 : else
2771 0 : pCodeCompleteWindow->ClearAndHide();
2772 0 : break;
2773 : case KEY_RETURN:
2774 0 : InsertSelectedEntry();
2775 0 : break;
2776 : case KEY_UP: case KEY_DOWN:
2777 0 : NotifyEvent nEvt( EVENT_KEYINPUT, NULL, &rKeyEvt );
2778 0 : PreNotify(nEvt);
2779 0 : break;
2780 : }
2781 : }
2782 0 : ListBox::KeyInput(rKeyEvt);
2783 0 : }
2784 :
2785 0 : void CodeCompleteListBox::HideAndRestoreFocus()
2786 : {
2787 0 : pCodeCompleteWindow->Hide();
2788 0 : pCodeCompleteWindow->pParent->GrabFocus();
2789 0 : }
2790 :
2791 0 : CodeCompleteWindow::CodeCompleteWindow( EditorWindow* pPar )
2792 : : Window( pPar ),
2793 : pParent( pPar ),
2794 0 : pListBox( new CodeCompleteListBox(this) )
2795 : {
2796 0 : SetSizePixel( Size(151,151) ); //default, later it changes
2797 0 : InitListBox();
2798 0 : }
2799 :
2800 0 : void CodeCompleteWindow::InitListBox()
2801 : {
2802 0 : pListBox->SetSizePixel( Size(150,150) ); //default, this will adopt the line length
2803 0 : pListBox->Show();
2804 0 : pListBox->EnableQuickSelection( false );
2805 0 : }
2806 :
2807 0 : void CodeCompleteWindow::InsertEntry( const OUString& aStr )
2808 : {
2809 0 : pListBox->InsertEntry( aStr );
2810 0 : }
2811 :
2812 0 : void CodeCompleteWindow::ClearListBox()
2813 : {
2814 0 : pListBox->Clear();
2815 0 : pListBox->aFuncBuffer.makeStringAndClear();
2816 0 : }
2817 :
2818 0 : void CodeCompleteWindow::SetTextSelection( const TextSelection& aSel )
2819 : {
2820 0 : aTextSelection = aSel;
2821 0 : }
2822 :
2823 0 : const TextSelection& CodeCompleteWindow::GetTextSelection() const
2824 : {
2825 0 : return aTextSelection;
2826 : }
2827 :
2828 0 : void CodeCompleteWindow::ResizeAndPositionListBox()
2829 : {
2830 0 : if( pListBox->GetEntryCount() >= 1 )
2831 : {// if there is at least one element inside
2832 : // calculate basic position: under the current line
2833 0 : Rectangle aRect = ( (TextEngine*) pParent->GetEditEngine() )->PaMtoEditCursor( pParent->GetEditView()->GetSelection().GetEnd() , false );
2834 0 : long nViewYOffset = pParent->GetEditView()->GetStartDocPos().Y();
2835 0 : Point aPos = aRect.BottomRight();// this variable will be used later (if needed)
2836 0 : aPos.Y() = (aPos.Y() - nViewYOffset) + nBasePad;
2837 :
2838 0 : OUString aLongestEntry = pListBox->GetEntry( 0 );// grab the longest one: max search
2839 0 : for( sal_Int32 i=1; i< pListBox->GetEntryCount(); ++i )
2840 : {
2841 0 : if( ((OUString) pListBox->GetEntry( i )).getLength() > aLongestEntry.getLength() )
2842 0 : aLongestEntry = pListBox->GetEntry( i );
2843 : }
2844 : // get column/line count
2845 0 : const sal_uInt16& nColumns = aLongestEntry.getLength();
2846 0 : const sal_uInt16 nLines = static_cast<sal_uInt16>( std::min( (sal_Int32) 6, pListBox->GetEntryCount() ));
2847 :
2848 0 : Size aSize = pListBox->CalcBlockSize( nColumns, nLines );
2849 : //set the size
2850 0 : SetSizePixel( aSize );
2851 : //1 px smaller, to see the border
2852 0 : aSize.setWidth( aSize.getWidth() - 1 );
2853 0 : aSize.setHeight( aSize.getHeight() - 1 );
2854 0 : pListBox->SetSizePixel( aSize );
2855 :
2856 : //calculate position
2857 0 : const Rectangle aVisArea( pParent->GetEditView()->GetStartDocPos(), pParent->GetOutputSizePixel() );//the visible area
2858 0 : const Point& aBottomPoint = aVisArea.BottomRight();
2859 :
2860 0 : if( aVisArea.TopRight().getY() + aPos.getY() + aSize.getHeight() > aBottomPoint.getY() )
2861 : {//clipped at the bottom: move it up
2862 0 : const long& nParentFontHeight = pParent->GetEditEngine()->GetFont().GetHeight();//parent's font (in the IDE): needed for height
2863 0 : aPos.Y() -= aSize.getHeight() + nParentFontHeight + nCursorPad;
2864 : }
2865 :
2866 0 : if( aVisArea.TopLeft().getX() + aPos.getX() + aSize.getWidth() > aBottomPoint.getX() )
2867 : {//clipped at the right side, move it a bit left
2868 0 : aPos.X() -= aSize.getWidth() + aVisArea.TopLeft().getX();
2869 : }
2870 : //set the position
2871 0 : SetPosPixel( aPos );
2872 : }
2873 0 : }
2874 :
2875 0 : void CodeCompleteWindow::SelectFirstEntry()
2876 : {
2877 0 : if( pListBox->GetEntryCount() > 0 )
2878 : {
2879 0 : pListBox->SelectEntryPos( 0 );
2880 : }
2881 0 : }
2882 :
2883 0 : void CodeCompleteWindow::ClearAndHide()
2884 : {
2885 0 : ClearListBox();
2886 0 : pListBox->HideAndRestoreFocus();
2887 0 : }
2888 :
2889 0 : UnoTypeCodeCompletetor::UnoTypeCodeCompletetor( const std::vector< OUString >& aVect, const OUString& sVarType )
2890 0 : : bCanComplete( true )
2891 : {
2892 0 : if( aVect.size() == 0 || sVarType.isEmpty() )
2893 : {
2894 0 : bCanComplete = false;//invalid parameters, nothing to code complete
2895 0 : return;
2896 : }
2897 :
2898 : try
2899 : {
2900 : // Get the base class for reflection:
2901 0 : xClass = css::reflection::theCoreReflection::get(
2902 0 : comphelper::getProcessComponentContext())->forName(sVarType);
2903 : }
2904 0 : catch( const Exception& )
2905 : {
2906 0 : bCanComplete = false;
2907 0 : return;
2908 : }
2909 :
2910 0 : unsigned int j = 1;//start from aVect[1]: aVect[0] is the variable name
2911 0 : OUString sMethName;
2912 :
2913 0 : while( j != aVect.size() )
2914 : {
2915 0 : sMethName = aVect[j];
2916 :
2917 0 : if( CodeCompleteOptions::IsExtendedTypeDeclaration() )
2918 : {
2919 0 : if( !CheckMethod(sMethName) && !CheckField(sMethName) )
2920 : {
2921 0 : bCanComplete = false;
2922 0 : break;
2923 : }
2924 : }
2925 : else
2926 : {
2927 0 : if( !CheckField(sMethName) )
2928 : {
2929 0 : bCanComplete = false;
2930 0 : break;
2931 : }
2932 : }
2933 :
2934 0 : ++j;
2935 0 : }
2936 : }
2937 :
2938 0 : std::vector< OUString > UnoTypeCodeCompletetor::GetXIdlClassMethods() const
2939 : {
2940 0 : std::vector< OUString > aRetVect;
2941 0 : if( bCanComplete && ( xClass != NULL ) )
2942 : {
2943 0 : Sequence< Reference< reflection::XIdlMethod > > aMethods = xClass->getMethods();
2944 0 : if( aMethods.getLength() != 0 )
2945 : {
2946 0 : for(sal_Int32 l = 0; l < aMethods.getLength(); ++l)
2947 : {
2948 0 : aRetVect.push_back( OUString(aMethods[l]->getName()) );
2949 : }
2950 0 : }
2951 : }
2952 0 : return aRetVect;//this is empty when cannot code complete
2953 : }
2954 :
2955 0 : std::vector< OUString > UnoTypeCodeCompletetor::GetXIdlClassFields() const
2956 : {
2957 0 : std::vector< OUString > aRetVect;
2958 0 : if( bCanComplete && ( xClass != NULL ) )
2959 : {
2960 0 : Sequence< Reference< reflection::XIdlField > > aFields = xClass->getFields();
2961 0 : if( aFields.getLength() != 0 )
2962 : {
2963 0 : for(sal_Int32 l = 0; l < aFields.getLength(); ++l)
2964 : {
2965 0 : aRetVect.push_back( OUString(aFields[l]->getName()) );
2966 : }
2967 0 : }
2968 : }
2969 0 : return aRetVect;//this is empty when cannot code complete
2970 : }
2971 :
2972 0 : bool UnoTypeCodeCompletetor::CanCodeComplete() const
2973 : {
2974 0 : return bCanComplete;
2975 : }
2976 :
2977 0 : bool UnoTypeCodeCompletetor::CheckField( const OUString& sFieldName )
2978 : {// modifies xClass!!!
2979 0 : Reference< reflection::XIdlField> xField = xClass->getField( sFieldName );
2980 0 : if( xField != NULL )
2981 : {
2982 0 : xClass = xField->getType();
2983 0 : if( xClass != NULL )
2984 : {
2985 0 : return true;
2986 : }
2987 : }
2988 0 : return false;
2989 : }
2990 :
2991 0 : bool UnoTypeCodeCompletetor::CheckMethod( const OUString& sMethName )
2992 : {// modifies xClass!!!
2993 0 : Reference< reflection::XIdlMethod> xMethod = xClass->getMethod( sMethName );
2994 0 : if( xMethod != NULL ) //method OK, check return type
2995 : {
2996 0 : xClass = xMethod->getReturnType();
2997 0 : if( xClass != NULL )
2998 : {
2999 0 : return true;
3000 : }
3001 : }
3002 0 : return false;
3003 : }
3004 :
3005 : } // namespace basctl
3006 :
3007 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|