1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_basctl.hxx"
30 
31 #include <vector>
32 #define _BASIC_TEXTPORTIONS
33 #include <basic/sbdef.hxx>
34 #include <ide_pch.hxx>
35 
36 
37 #include <tools/urlobj.hxx>
38 #include <unotools/charclass.hxx>
39 #include <svl/urihelper.hxx>
40 #include <basic/sbx.hxx>
41 #include <vcl/sound.hxx>
42 #include <svtools/xtextedt.hxx>
43 #include <svtools/txtattr.hxx>
44 #include <svtools/textwindowpeer.hxx>
45 #include <basic/sbuno.hxx>
46 
47 #include <helpid.hrc>
48 #include <baside2.hrc>
49 #include <baside2.hxx>
50 #include <brkdlg.hxx>
51 #include <objdlg.hxx>
52 #include <basobj.hxx>
53 #include <iderdll.hxx>
54 #include <iderdll2.hxx>
55 #include <vcl/taskpanelist.hxx>
56 #include <vcl/help.hxx>
57 
58 //#ifndef _SFX_HELP_HXX //autogen
59 //#include <sfx2/sfxhelp.hxx>
60 //#endif
61 #include <unotools/sourceviewconfig.hxx>
62 
63 #ifndef _COM_SUN_STAR_SCRIPT_XLIBRYARYCONTAINER2_HPP_
64 #include <com/sun/star/script/XLibraryContainer2.hpp>
65 #endif
66 #include <comphelper/processfactory.hxx>
67 
68 
69 using namespace ::com::sun::star;
70 using namespace ::com::sun::star::uno;
71 
72 
73 long nVirtToolBoxHeight;	// wird im WatchWindow init., im Stackwindow verw.
74 long nHeaderBarHeight;
75 
76 #define SCROLL_LINE		12
77 #define SCROLL_PAGE		60
78 
79 #define DWBORDER		3
80 
81 static const char cSuffixes[] = "%&!#@$";
82 
83 MapUnit eEditMapUnit = MAP_100TH_MM;
84 
85 
86 // #108672 Helper functions to get/set text in TextEngine
87 // using the stream interface (get/setText() only supports
88 // tools Strings limited to 64K).
89 ::rtl::OUString getTextEngineText( ExtTextEngine* pEngine )
90 {
91     SvMemoryStream aMemStream;
92     aMemStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
93     aMemStream.SetLineDelimiter( LINEEND_LF );
94     pEngine->Write( aMemStream );
95     sal_uLong nSize = aMemStream.Tell();
96     ::rtl::OUString aText( (const sal_Char*)aMemStream.GetData(),
97         nSize, RTL_TEXTENCODING_UTF8 );
98     return aText;
99 }
100 
101 void setTextEngineText( ExtTextEngine* pEngine, const ::rtl::OUString aStr )
102 {
103     pEngine->SetText( String() );
104     ::rtl::OString aUTF8Str = ::rtl::OUStringToOString( aStr, RTL_TEXTENCODING_UTF8 );
105 	SvMemoryStream aMemStream( (void*)aUTF8Str.getStr(), aUTF8Str.getLength(),
106         STREAM_READ | STREAM_SEEK_TO_BEGIN );
107     aMemStream.SetStreamCharSet( RTL_TEXTENCODING_UTF8 );
108     aMemStream.SetLineDelimiter( LINEEND_LF );
109 	pEngine->Read( aMemStream );
110 }
111 
112 void lcl_DrawIDEWindowFrame( DockingWindow* pWin )
113 {
114     // The result of using explicit colors here appears to be harmless when
115     // switching to high contrast mode:
116 	if ( !pWin->IsFloatingMode() )
117 	{
118 		Size aSz = pWin->GetOutputSizePixel();
119 		const Color aOldLineColor( pWin->GetLineColor() );
120 		pWin->SetLineColor( Color( COL_WHITE ) );
121 		// oben eine weisse..
122 		pWin->DrawLine( Point( 0, 0 ), Point( aSz.Width(), 0 ) );
123 		// unten eine schwarze...
124 		pWin->SetLineColor( Color( COL_BLACK ) );
125 		pWin->DrawLine( Point( 0, aSz.Height() - 1 ), Point( aSz.Width(), aSz.Height() - 1 ) );
126 		pWin->SetLineColor( aOldLineColor );
127 	}
128 }
129 
130 void lcl_SeparateNameAndIndex( const String& rVName, String& rVar, String& rIndex )
131 {
132 	rVar = rVName;
133 	rIndex.Erase();
134 	sal_uInt16 nIndexStart = rVar.Search( '(' );
135 	if ( nIndexStart != STRING_NOTFOUND )
136 	{
137 		sal_uInt16 nIndexEnd = rVar.Search( ')', nIndexStart );
138 		if ( nIndexStart != STRING_NOTFOUND )
139 		{
140 			rIndex = rVar.Copy( nIndexStart+1, nIndexEnd-nIndexStart-1 );
141 			rVar.Erase( nIndexStart );
142 			rVar.EraseTrailingChars();
143 			rIndex.EraseLeadingChars();
144 			rIndex.EraseTrailingChars();
145 		}
146 	}
147 
148 	if ( rVar.Len() )
149 	{
150 		sal_uInt16 nLastChar = rVar.Len()-1;
151 		if ( strchr( cSuffixes, rVar.GetChar( nLastChar ) ) )
152 			rVar.Erase( nLastChar, 1 );
153 	}
154 	if ( rIndex.Len() )
155 	{
156 		sal_uInt16 nLastChar = rIndex.Len()-1;
157 		if ( strchr( cSuffixes, rIndex.GetChar( nLastChar ) ) )
158 			rIndex.Erase( nLastChar, 1 );
159 	}
160 }
161 
162 
163 EditorWindow::EditorWindow( Window* pParent ) :
164 	Window( pParent, WB_BORDER )
165 {
166 	bDoSyntaxHighlight = sal_True;
167 	bDelayHighlight = sal_True;
168 	pModulWindow = 0;
169 	pEditView = 0;
170 	pEditEngine = 0;
171     pSourceViewConfig = new utl::SourceViewConfig;
172 	bHighlightning = sal_False;
173 	pProgress = 0;
174 	nCurTextWidth = 0;
175 	SetBackground(
176         Wallpaper(GetSettings().GetStyleSettings().GetFieldColor()));
177 	SetPointer( Pointer( POINTER_TEXT ) );
178 
179 	SetHelpId( HID_BASICIDE_EDITORWINDOW );
180     pSourceViewConfig->AddListener(this);
181 }
182 
183 
184 
185 __EXPORT EditorWindow::~EditorWindow()
186 {
187     pSourceViewConfig->RemoveListener(this);
188     delete pSourceViewConfig;
189 
190 	aSyntaxIdleTimer.Stop();
191 
192 	if ( pEditEngine )
193 	{
194 		EndListening( *pEditEngine );
195 		pEditEngine->RemoveView( pEditView );
196 //		pEditEngine->SetViewWin( 0 );
197 		delete pEditView;
198 		delete pEditEngine;
199 	}
200 }
201 
202 String EditorWindow::GetWordAtCursor()
203 {
204     String aWord;
205 
206     if ( pEditView )
207     {
208         TextEngine* pTextEngine = pEditView->GetTextEngine();
209         if ( pTextEngine )
210         {
211             // check first, if the cursor is at a help URL
212             const TextSelection& rSelection = pEditView->GetSelection();
213             const TextPaM& rSelStart = rSelection.GetStart();
214             const TextPaM& rSelEnd = rSelection.GetEnd();
215             String aText = pTextEngine->GetText( rSelEnd.GetPara() );
216             CharClass aClass( ::comphelper::getProcessServiceFactory() , Application::GetSettings().GetLocale() );
217             xub_StrLen nSelStart = static_cast< xub_StrLen >( rSelStart.GetIndex() );
218             xub_StrLen nSelEnd = static_cast< xub_StrLen >( rSelEnd.GetIndex() );
219             xub_StrLen nLength = static_cast< xub_StrLen >( aText.Len() );
220             xub_StrLen nStart = 0;
221             xub_StrLen nEnd = nLength;
222             while ( nStart < nLength )
223             {
224                 String aURL( URIHelper::FindFirstURLInText( aText, nStart, nEnd, aClass ) );
225 	            INetURLObject aURLObj( aURL );
226                 if ( aURLObj.GetProtocol() == INET_PROT_VND_SUN_STAR_HELP
227                      && nSelStart >= nStart && nSelStart <= nEnd && nSelEnd >= nStart && nSelEnd <= nEnd )
228                 {
229                     aWord = aURL;
230                     break;
231                 }
232                 nStart = nEnd;
233                 nEnd = nLength;
234             }
235 
236             // Nicht den Selektierten Bereich, sondern an der CursorPosition,
237             // falls Teil eines Worts markiert.
238             if ( !aWord.Len() )
239                 aWord = pTextEngine->GetWord( rSelEnd );
240 
241             // Kann leer sein, wenn komplettes Word markiert, da Cursor dahinter.
242             if ( !aWord.Len() && pEditView->HasSelection() )
243                 aWord = pTextEngine->GetWord( rSelStart );
244         }
245     }
246 
247     return aWord;
248 }
249 
250 void __EXPORT EditorWindow::RequestHelp( const HelpEvent& rHEvt )
251 {
252     sal_Bool bDone = sal_False;
253 
254 	// Sollte eigentlich mal aktiviert werden...
255 	if ( pEditEngine )
256 	{
257         if ( rHEvt.GetMode() & HELPMODE_CONTEXT )
258 		{
259 			String aKeyword = GetWordAtCursor();
260 			Application::GetHelp()->SearchKeyword( aKeyword );
261             bDone = sal_True;
262         }
263 		else if ( rHEvt.GetMode() & HELPMODE_QUICK )
264 		{
265 			String aHelpText;
266 			Point aTopLeft;
267 			if ( StarBASIC::IsRunning() )
268 			{
269 				Point aWindowPos = rHEvt.GetMousePosPixel();
270 				aWindowPos = ScreenToOutputPixel( aWindowPos );
271 				Point aDocPos = GetEditView()->GetDocPos( aWindowPos );
272 				TextPaM aCursor = GetEditView()->GetTextEngine()->GetPaM( aDocPos, sal_False );
273 				TextPaM aStartOfWord;
274 				String aWord = GetEditView()->GetTextEngine()->GetWord( aCursor, &aStartOfWord );
275 				if ( aWord.Len() && !ByteString( aWord, RTL_TEXTENCODING_UTF8 ).IsNumericAscii() )
276 				{
277 					sal_uInt16 nLastChar =aWord.Len()-1;
278 					if ( strchr( cSuffixes, aWord.GetChar( nLastChar ) ) )
279 						aWord.Erase( nLastChar, 1 );
280 					SbxBase* pSBX = StarBASIC::FindSBXInCurrentScope( aWord );
281 					if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) )
282 					{
283 						SbxVariable* pVar = (SbxVariable*)pSBX;
284 						SbxDataType eType = pVar->GetType();
285 						if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
286 							// Kann zu Absturz, z.B. bei Selections-Objekt fuehren
287 							// Type == Object heisst nicht, dass pVar == Object!
288 							; // aHelpText = ((SbxObject*)pVar)->GetClassName();
289 						else if ( eType & SbxARRAY )
290 							; // aHelpText = "{...}";
291 						else if ( (sal_uInt8)eType != (sal_uInt8)SbxEMPTY )
292 						{
293 							aHelpText = pVar->GetName();
294 							if ( !aHelpText.Len() ) 	// Bei Uebergabeparametern wird der Name nicht kopiert
295 								aHelpText = aWord;
296 							aHelpText += '=';
297 							aHelpText += pVar->GetString();
298 						}
299 					}
300 					if ( aHelpText.Len() )
301 					{
302 						aTopLeft = GetEditView()->GetTextEngine()->PaMtoEditCursor( aStartOfWord ).BottomLeft();
303 						aTopLeft = GetEditView()->GetWindowPos( aTopLeft );
304 						aTopLeft.X() += 5;
305 						aTopLeft.Y() += 5;
306 						aTopLeft = OutputToScreenPixel( aTopLeft );
307 					}
308 				}
309 			}
310 			Help::ShowQuickHelp( this, Rectangle( aTopLeft, Size( 1, 1 ) ), aHelpText, QUICKHELP_TOP|QUICKHELP_LEFT);
311             bDone = sal_True;
312 		}
313 	}
314 
315     if ( !bDone )
316         Window::RequestHelp( rHEvt );
317 }
318 
319 
320 void __EXPORT EditorWindow::Resize()
321 {
322 	// ScrollBars, etc. passiert in Adjust...
323 	if ( pEditView )
324 	{
325 		long nVisY = pEditView->GetStartDocPos().Y();
326 //		pEditView->SetOutputArea( Rectangle( Point( 0, 0 ), GetOutputSize() ) );
327 		pEditView->ShowCursor();
328 		Size aOutSz( GetOutputSizePixel() );
329 		long nMaxVisAreaStart = pEditView->GetTextEngine()->GetTextHeight() - aOutSz.Height();
330 		if ( nMaxVisAreaStart < 0 )
331 			nMaxVisAreaStart = 0;
332 		if ( pEditView->GetStartDocPos().Y() > nMaxVisAreaStart )
333 		{
334 			Point aStartDocPos( pEditView->GetStartDocPos() );
335 			aStartDocPos.Y() = nMaxVisAreaStart;
336 			pEditView->SetStartDocPos( aStartDocPos );
337 			pEditView->ShowCursor();
338 			pModulWindow->GetBreakPointWindow().GetCurYOffset() = aStartDocPos.Y();
339 		}
340 		InitScrollBars();
341 		if ( nVisY != pEditView->GetStartDocPos().Y() )
342 			Invalidate();
343 	}
344 }
345 
346 
347 
348 void __EXPORT EditorWindow::MouseMove( const MouseEvent &rEvt )
349 {
350 	if ( pEditView )
351 		pEditView->MouseMove( rEvt );
352 }
353 
354 
355 
356 void __EXPORT EditorWindow::MouseButtonUp( const MouseEvent &rEvt )
357 {
358 	if ( pEditView )
359 	{
360 		pEditView->MouseButtonUp( rEvt );
361         SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
362         if ( pBindings )
363             pBindings->Invalidate( SID_BASICIDE_STAT_POS );
364 	}
365 }
366 
367 void __EXPORT EditorWindow::MouseButtonDown( const MouseEvent &rEvt )
368 {
369 	GrabFocus();
370 	if ( pEditView )
371 	{
372 		pEditView->MouseButtonDown( rEvt );
373 	}
374 }
375 
376 void __EXPORT EditorWindow::Command( const CommandEvent& rCEvt )
377 {
378 	if ( pEditView )
379 	{
380 		pEditView->Command( rCEvt );
381 		if ( ( rCEvt.GetCommand() == COMMAND_WHEEL ) ||
382 			 ( rCEvt.GetCommand() == COMMAND_STARTAUTOSCROLL ) ||
383 			 ( rCEvt.GetCommand() == COMMAND_AUTOSCROLL ) )
384 		{
385 			HandleScrollCommand( rCEvt, pModulWindow->GetHScrollBar(), &pModulWindow->GetEditVScrollBar() );
386 		}
387 	}
388 }
389 
390 sal_Bool EditorWindow::ImpCanModify()
391 {
392 	sal_Bool bCanModify = sal_True;
393 	if ( StarBASIC::IsRunning() )
394 	{
395 		// Wenn im Trace-Mode, entweder Trace abbrechen oder
396 		// Eingabe verweigern
397 		// Im Notify bei Basic::Stoped die Markierungen in den Modulen
398 		// entfernen!
399 		if ( QueryBox( 0, WB_OK_CANCEL, String( IDEResId( RID_STR_WILLSTOPPRG ) ) ).Execute() == RET_OK )
400 		{
401 			pModulWindow->GetBasicStatus().bIsRunning = sal_False;
402 			BasicIDE::StopBasic();
403 		}
404 		else
405 			bCanModify = sal_False;
406 	}
407 	return bCanModify;
408 }
409 
410 void __EXPORT EditorWindow::KeyInput( const KeyEvent& rKEvt )
411 {
412 	if ( !pEditView )	// Passiert unter W95 bei letzte Version, Ctrl-Tab
413 		return;
414 
415 #if OSL_DEBUG_LEVEL > 1
416     Range aRange = pModulWindow->GetHScrollBar()->GetRange(); (void)aRange;
417     long nVisSz = pModulWindow->GetHScrollBar()->GetVisibleSize(); (void)nVisSz;
418     long nPapSz = pModulWindow->GetHScrollBar()->GetPageSize(); (void)nPapSz;
419     long nLinSz = pModulWindow->GetHScrollBar()->GetLineSize(); (void)nLinSz;
420     long nThumb = pModulWindow->GetHScrollBar()->GetThumbPos(); (void)nThumb;
421 #endif
422 	sal_Bool bDone = sal_False;
423 	sal_Bool bWasModified = pEditEngine->IsModified();
424 	if ( !TextEngine::DoesKeyChangeText( rKEvt ) || ImpCanModify() )
425 	{
426 		if ( ( rKEvt.GetKeyCode().GetCode() == KEY_A) && rKEvt.GetKeyCode().IsMod1() )
427 			pEditView->SetSelection( TextSelection( TextPaM( 0, 0 ), TextPaM( 0xFFFFFFFF, 0xFFFF ) ) );
428 		else if ( ( rKEvt.GetKeyCode().GetCode() == KEY_Y ) && rKEvt.GetKeyCode().IsMod1() )
429 			bDone = sal_True; // CTRL-Y schlucken, damit kein Vorlagenkatalog
430 		else
431 		{
432 			if ( ( rKEvt.GetKeyCode().GetCode() == KEY_TAB ) && !rKEvt.GetKeyCode().IsMod1() &&
433 				  !rKEvt.GetKeyCode().IsMod2() && !GetEditView()->IsReadOnly() )
434 			{
435 				TextSelection aSel( pEditView->GetSelection() );
436 				if ( aSel.GetStart().GetPara() != aSel.GetEnd().GetPara() )
437 				{
438 					bDelayHighlight = sal_False;
439 					if ( !rKEvt.GetKeyCode().IsShift() )
440 						pEditView->IndentBlock();
441 					else
442 						pEditView->UnindentBlock();
443 					bDelayHighlight = sal_True;
444 					bDone = sal_True;
445 				}
446 			}
447 			if ( !bDone )
448 				bDone = pEditView->KeyInput( rKEvt );
449 		}
450 	}
451 	if ( !bDone )
452 	{
453 		if ( !SfxViewShell::Current()->KeyInput( rKEvt ) )
454 			Window::KeyInput( rKEvt );
455 	}
456 	else
457 	{
458         SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
459         if ( pBindings )
460         {
461             pBindings->Invalidate( SID_BASICIDE_STAT_POS );
462             if ( rKEvt.GetKeyCode().GetGroup() == KEYGROUP_CURSOR )
463                 pBindings->Update( SID_BASICIDE_STAT_POS );
464             if ( !bWasModified && pEditEngine->IsModified() )
465             {
466                 pBindings->Invalidate( SID_SAVEDOC );
467                 pBindings->Invalidate( SID_DOC_MODIFIED );
468                 pBindings->Invalidate( SID_UNDO );
469             }
470             if ( rKEvt.GetKeyCode().GetCode() == KEY_INSERT )
471                 pBindings->Invalidate( SID_ATTR_INSERT );
472         }
473 	}
474 }
475 
476 void __EXPORT EditorWindow::Paint( const Rectangle& rRect )
477 {
478 	if ( !pEditEngine )		// spaetestens jetzt brauche ich sie...
479 		CreateEditEngine();
480 
481 	pEditView->Paint( rRect );
482 }
483 
484 void __EXPORT EditorWindow::LoseFocus()
485 {
486 	SetSourceInBasic();
487 	Window::LoseFocus();
488 }
489 
490 sal_Bool EditorWindow::SetSourceInBasic( sal_Bool bQuiet )
491 {
492 	(void)bQuiet;
493 
494 	sal_Bool bChanged = sal_False;
495 	if ( pEditEngine && pEditEngine->IsModified()
496 		&& !GetEditView()->IsReadOnly() )	// Added because of #i60626, otherwise
497 			// any read only bug in the text engine could lead to a crash later
498 	{
499         if ( !StarBASIC::IsRunning() ) // Nicht zur Laufzeit!
500 		{
501             ::rtl::OUString aModule = getTextEngineText( pEditEngine );
502 
503             // update module in basic
504 #ifdef DBG_UTIL
505             SbModule* pModule = pModulWindow->GetSbModule();
506 #endif
507             DBG_ASSERT(pModule, "EditorWindow::SetSourceInBasic: No Module found!");
508 
509             // update module in module window
510             pModulWindow->SetModule( aModule );
511 
512             // update module in library
513             ScriptDocument aDocument( pModulWindow->GetDocument() );
514             String aLibName = pModulWindow->GetLibName();
515 	        String aName = pModulWindow->GetName();
516             OSL_VERIFY( aDocument.updateModule( aLibName, aName, aModule ) );
517 
518             pEditEngine->SetModified( sal_False );
519             BasicIDE::MarkDocumentModified( aDocument );
520             bChanged = sal_True;
521 		}
522 	}
523 	return bChanged;
524 }
525 
526 
527 // Returns the position of the last character of any of the following
528 // EOL char combinations: CR, CR/LF, LF, return -1 if no EOL is found
529 sal_Int32 searchEOL( const ::rtl::OUString& rStr, sal_Int32 fromIndex )
530 {
531 	sal_Int32 iRetPos = -1;
532 
533 	sal_Int32 iLF = rStr.indexOf( LINE_SEP, fromIndex );
534 	if( iLF != -1 )
535 	{
536 		iRetPos = iLF;
537 	}
538 	else
539 	{
540 		iRetPos = rStr.indexOf( LINE_SEP_CR, fromIndex );
541 	}
542 	return iRetPos;
543 }
544 
545 
546 void EditorWindow::CreateEditEngine()
547 {
548 	if ( pEditEngine )
549 		return;
550 
551 	pEditEngine = new ExtTextEngine;
552 	pEditView = new ExtTextView( pEditEngine, this );
553 	pEditView->SetAutoIndentMode( sal_True );
554 	pEditEngine->SetUpdateMode( sal_False );
555 	pEditEngine->InsertView( pEditView );
556 
557 	ImplSetFont();
558 
559 	aSyntaxIdleTimer.SetTimeout( 200 );
560 	aSyntaxIdleTimer.SetTimeoutHdl( LINK( this, EditorWindow, SyntaxTimerHdl ) );
561 
562 	aHighlighter.initialize( HIGHLIGHT_BASIC );
563 
564 	sal_Bool bWasDoSyntaxHighlight = bDoSyntaxHighlight;
565 	bDoSyntaxHighlight = sal_False;	// Bei grossen Texten zu langsam...
566     ::rtl::OUString aOUSource( pModulWindow->GetModule() );
567 	sal_Int32 nLines = 0;
568     sal_Int32 nIndex = -1;
569     do
570     {
571         nLines++;
572 		nIndex = searchEOL( aOUSource, nIndex+1 );
573     }
574     while ( nIndex >= 0 );
575 
576 	// nLines*4: SetText+Formatting+DoHighlight+Formatting
577 	// 1 Formatting koennte eingespart werden, aber dann wartet man
578 	// bei einem langen Sourcecode noch laenger auf den Text...
579 	pProgress = new ProgressInfo( IDE_DLL()->GetShell()->GetViewFrame()->GetObjectShell(), String( IDEResId( RID_STR_GENERATESOURCE ) ), nLines*4 );
580     setTextEngineText( pEditEngine, aOUSource );
581 
582 	pEditView->SetStartDocPos( Point( 0, 0 ) );
583 	pEditView->SetSelection( TextSelection() );
584 	pModulWindow->GetBreakPointWindow().GetCurYOffset() = 0;
585 	pEditEngine->SetUpdateMode( sal_True );
586 	Update();	// Es wurde bei UpdateMode = sal_True nur Invalidiert
587 
588 	// Die anderen Fenster auch, damit keine halben Sachen auf dem Bildschirm!
589 	pModulWindow->GetLayout()->GetWatchWindow().Update();
590 	pModulWindow->GetLayout()->GetStackWindow().Update();
591 	pModulWindow->GetBreakPointWindow().Update();
592 
593 	pEditView->ShowCursor( sal_True, sal_True );
594 
595 	StartListening( *pEditEngine );
596 
597 	// Das Syntax-Highlightning legt ein rel. groesse VDev an.
598 	aSyntaxIdleTimer.Stop();
599 	bDoSyntaxHighlight = bWasDoSyntaxHighlight;
600 
601 
602 	for ( sal_uInt16 nLine = 0; nLine < nLines; nLine++ )
603 		aSyntaxLineTable.Insert( nLine, (void*)(sal_uInt16)1 );
604 	ForceSyntaxTimeout();
605 
606 	DELETEZ( pProgress );
607 
608 	pEditView->EraseVirtualDevice();
609 	pEditEngine->SetModified( sal_False );
610 	pEditEngine->EnableUndo( sal_True );
611 
612 	InitScrollBars();
613 
614     SfxBindings* pBindings = BasicIDE::GetBindingsPtr();
615     if ( pBindings )
616         pBindings->Invalidate( SID_BASICIDE_STAT_POS );
617 
618 	DBG_ASSERT( pModulWindow->GetBreakPointWindow().GetCurYOffset() == 0, "CreateEditEngine: Brechpunkte verschoben?" );
619 
620     // set readonly mode for readonly libraries
621     ScriptDocument aDocument( pModulWindow->GetDocument() );
622     ::rtl::OUString aOULibName( pModulWindow->GetLibName() );
623     Reference< script::XLibraryContainer2 > xModLibContainer( aDocument.getLibraryContainer( E_SCRIPTS ), UNO_QUERY );
624     if ( xModLibContainer.is() && xModLibContainer->hasByName( aOULibName ) && xModLibContainer->isLibraryReadOnly( aOULibName ) )
625     {
626         pModulWindow->SetReadOnly( sal_True );
627     }
628 
629     if ( aDocument.isDocument() && aDocument.isReadOnly() )
630 		pModulWindow->SetReadOnly( sal_True );
631 }
632 
633 // virtual
634 void EditorWindow::DataChanged(DataChangedEvent const & rDCEvt)
635 {
636     Window::DataChanged(rDCEvt);
637     if (rDCEvt.GetType() == DATACHANGED_SETTINGS
638         && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
639     {
640         Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
641         if (aColor
642             != rDCEvt.GetOldSettings()->GetStyleSettings().GetFieldColor())
643         {
644             SetBackground(Wallpaper(aColor));
645             Invalidate();
646         }
647         if (pEditEngine != 0)
648         {
649             aColor = GetSettings().GetStyleSettings().GetFieldTextColor();
650             if (aColor != rDCEvt.GetOldSettings()->
651                 GetStyleSettings().GetFieldTextColor())
652             {
653                 Font aFont(pEditEngine->GetFont());
654                 aFont.SetColor(aColor);
655                 pEditEngine->SetFont(aFont);
656             }
657         }
658     }
659 }
660 
661 void EditorWindow::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint )
662 {
663 	if ( rHint.ISA( TextHint ) )
664 	{
665 		const TextHint& rTextHint = (const TextHint&)rHint;
666 		if( rTextHint.GetId() == TEXT_HINT_VIEWSCROLLED )
667 		{
668 			if ( pModulWindow->GetHScrollBar() )
669 				pModulWindow->GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
670 			pModulWindow->GetEditVScrollBar().SetThumbPos( pEditView->GetStartDocPos().Y() );
671 			pModulWindow->GetBreakPointWindow().DoScroll
672 				( 0, pModulWindow->GetBreakPointWindow().GetCurYOffset() - pEditView->GetStartDocPos().Y() );
673 		}
674 		else if( rTextHint.GetId() == TEXT_HINT_TEXTHEIGHTCHANGED )
675 		{
676 			if ( pEditView->GetStartDocPos().Y() )
677 			{
678 				long nOutHeight = GetOutputSizePixel().Height();
679 				long nTextHeight = pEditEngine->GetTextHeight();
680 				if ( nTextHeight < nOutHeight )
681 					pEditView->Scroll( 0, pEditView->GetStartDocPos().Y() );
682 			}
683 
684 			SetScrollBarRanges();
685 		}
686 		else if( rTextHint.GetId() == TEXT_HINT_TEXTFORMATTED )
687 		{
688 			if ( pModulWindow->GetHScrollBar() )
689 			{
690 				sal_uLong nWidth = pEditEngine->CalcTextWidth();
691 				if ( (long)nWidth != nCurTextWidth )
692 				{
693 					nCurTextWidth = nWidth;
694 					pModulWindow->GetHScrollBar()->SetRange( Range( 0, (long)nCurTextWidth-1) );
695 					pModulWindow->GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
696 				}
697 			}
698 			long nPrevTextWidth = nCurTextWidth;
699 			nCurTextWidth = pEditEngine->CalcTextWidth();
700 			if ( nCurTextWidth != nPrevTextWidth )
701 				SetScrollBarRanges();
702 		}
703 		else if( rTextHint.GetId() == TEXT_HINT_PARAINSERTED )
704 		{
705 			ParagraphInsertedDeleted( rTextHint.GetValue(), sal_True );
706 			DoDelayedSyntaxHighlight( rTextHint.GetValue() );
707 		}
708 		else if( rTextHint.GetId() == TEXT_HINT_PARAREMOVED )
709 		{
710 			ParagraphInsertedDeleted( rTextHint.GetValue(), sal_False );
711 		}
712 		else if( rTextHint.GetId() == TEXT_HINT_PARACONTENTCHANGED )
713 		{
714 			DoDelayedSyntaxHighlight( rTextHint.GetValue() );
715 		}
716 	}
717 }
718 
719 void EditorWindow::ConfigurationChanged( utl::ConfigurationBroadcaster*, sal_uInt32 )
720 {
721     ImplSetFont();
722 }
723 
724 void EditorWindow::SetScrollBarRanges()
725 {
726 	// Extra-Methode, nicht InitScrollBars, da auch fuer EditEngine-Events.
727 	if ( !pEditEngine )
728 		return;
729 
730 	if ( pModulWindow->GetHScrollBar() )
731 		pModulWindow->GetHScrollBar()->SetRange( Range( 0, nCurTextWidth-1 ) );
732 
733 	pModulWindow->GetEditVScrollBar().SetRange( Range( 0, pEditEngine->GetTextHeight()-1 ) );
734 }
735 
736 void EditorWindow::InitScrollBars()
737 {
738 	if ( !pEditEngine )
739 		return;
740 
741 	SetScrollBarRanges();
742 	Size aOutSz( GetOutputSizePixel() );
743 	pModulWindow->GetEditVScrollBar().SetVisibleSize( aOutSz.Height() );
744 	pModulWindow->GetEditVScrollBar().SetPageSize( aOutSz.Height() * 8 / 10 );
745 	pModulWindow->GetEditVScrollBar().SetLineSize( GetTextHeight() );
746 	pModulWindow->GetEditVScrollBar().SetThumbPos( pEditView->GetStartDocPos().Y() );
747 	pModulWindow->GetEditVScrollBar().Show();
748 
749 	if ( pModulWindow->GetHScrollBar() )
750 	{
751 		pModulWindow->GetHScrollBar()->SetVisibleSize( aOutSz.Width() );
752 		pModulWindow->GetHScrollBar()->SetPageSize( aOutSz.Width() * 8 / 10 );
753 		pModulWindow->GetHScrollBar()->SetLineSize( GetTextWidth( 'x' ) );
754 		pModulWindow->GetHScrollBar()->SetThumbPos( pEditView->GetStartDocPos().X() );
755 		pModulWindow->GetHScrollBar()->Show();
756 	}
757 }
758 
759 void EditorWindow::ImpDoHighlight( sal_uLong nLine )
760 {
761 	if ( bDoSyntaxHighlight )
762 	{
763 		String aLine( pEditEngine->GetText( nLine ) );
764 		Range aChanges = aHighlighter.notifyChange( nLine, 0, &aLine, 1 );
765 		if ( aChanges.Len() )
766 		{
767 			for ( long n = aChanges.Min() + 1; n <= aChanges.Max(); n++ )
768 				aSyntaxLineTable.Insert( n, (void*)(sal_uLong)1 );
769 			aSyntaxIdleTimer.Start();
770 		}
771 
772 		sal_Bool bWasModified = pEditEngine->IsModified();
773 		pEditEngine->RemoveAttribs( nLine, sal_True );
774 		HighlightPortions aPortions;
775 		aHighlighter.getHighlightPortions( nLine, aLine, aPortions );
776 
777 		for ( size_t i = 0; i < aPortions.size(); i++ )
778 		{
779 			HighlightPortion& r = aPortions[i];
780 			const Color& rColor = ((ModulWindowLayout*)pModulWindow->GetLayoutWindow())->getSyntaxColor(r.tokenType);
781 			pEditEngine->SetAttrib( TextAttribFontColor( rColor ), nLine, r.nBegin, r.nEnd, sal_True );
782 		}
783 
784 		// Das Highlighten soll kein Modify setzen
785 		pEditEngine->SetModified( bWasModified );
786 	}
787 }
788 
789 void EditorWindow::ImplSetFont()
790 {
791     if ( pSourceViewConfig )
792 	{
793 		String sFontName = pSourceViewConfig->GetFontName();
794 		if ( !sFontName.Len() )
795 		{
796 			Font aTmpFont( OutputDevice::GetDefaultFont( DEFAULTFONT_FIXED, Application::GetSettings().GetUILanguage(), 0 , this ) );
797 			sFontName = aTmpFont.GetName();
798 		}
799 		Size aFontSize( 0, pSourceViewConfig->GetFontHeight() );
800 		Font aFont( sFontName, aFontSize );
801 		aFont.SetColor( GetSettings().GetStyleSettings().GetFieldTextColor() );
802 		SetPointFont( aFont );
803 		aFont = GetFont();
804 
805 		if ( pModulWindow )
806 			pModulWindow->GetBreakPointWindow().SetFont( aFont );
807 
808 		if ( pEditEngine )
809 		{
810 			sal_Bool bModified = pEditEngine->IsModified();
811 			pEditEngine->SetFont( aFont );
812 			pEditEngine->SetModified( bModified );
813 		}
814 	}
815 }
816 
817 void EditorWindow::DoSyntaxHighlight( sal_uLong nPara )
818 {
819 	// Durch das DelayedSyntaxHighlight kann es passieren,
820 	// dass die Zeile nicht mehr existiert!
821 	if ( nPara < pEditEngine->GetParagraphCount() )
822 	{
823 		// leider weis ich nicht, ob genau diese Zeile Modified() ...
824 		if ( pProgress )
825 			pProgress->StepProgress();
826 		ImpDoHighlight( nPara );
827 	}
828 }
829 
830 void EditorWindow::DoDelayedSyntaxHighlight( sal_uLong nPara )
831 {
832 	// Zeile wird nur in 'Liste' aufgenommen, im TimerHdl abgearbeitet.
833 	// => Nicht Absaetze manipulieren, waehrend EditEngine formatiert.
834 	if ( pProgress )
835 		pProgress->StepProgress();
836 
837 	if ( !bHighlightning && bDoSyntaxHighlight )
838 	{
839 		if ( bDelayHighlight )
840 		{
841 			aSyntaxLineTable.Insert( nPara, (void*)(sal_uLong)1 );
842 			aSyntaxIdleTimer.Start();
843 		}
844 		else
845 			DoSyntaxHighlight( nPara );
846 	}
847 }
848 
849 IMPL_LINK( EditorWindow, SyntaxTimerHdl, Timer *, EMPTYARG )
850 {
851 	DBG_ASSERT( pEditView, "Noch keine View, aber Syntax-Highlight ?!" );
852 
853 	sal_Bool bWasModified = pEditEngine->IsModified();
854 	// pEditEngine->SetUpdateMode( sal_False );
855 
856 	bHighlightning = sal_True;
857 	sal_uInt16 nLine;
858 	void* p = aSyntaxLineTable.First();
859 	while ( p )
860 	{
861 		nLine = (sal_uInt16)aSyntaxLineTable.GetCurKey();
862 		DoSyntaxHighlight( nLine );
863 		p = aSyntaxLineTable.Next();
864 	}
865 
866     // MT: Removed, because of idle format now when set/remove attribs...
867     // pEditView->SetAutoScroll( sal_False );  // #101043# Don't scroll because of syntax highlight
868     // pEditEngine->SetUpdateMode( sal_True );
869 	// pEditView->ShowCursor( sal_False, sal_True );
870     // pEditView->SetAutoScroll( sal_True );
871 
872     // #i45572#
873     if ( pEditView )
874         pEditView->ShowCursor( sal_False, sal_True );
875 
876 	pEditEngine->SetModified( bWasModified );
877 
878 	aSyntaxLineTable.Clear();
879 	bHighlightning = sal_False;
880 
881 	return 0;
882 }
883 
884 void EditorWindow::ParagraphInsertedDeleted( sal_uLong nPara, sal_Bool bInserted )
885 {
886 	if ( pProgress )
887 		pProgress->StepProgress();
888 
889 	if ( !bInserted && ( nPara == TEXT_PARA_ALL ) )
890 	{
891 		pModulWindow->GetBreakPoints().reset();
892 		pModulWindow->GetBreakPointWindow().Invalidate();
893 		aHighlighter.initialize( HIGHLIGHT_BASIC );
894 	}
895 	else
896 	{
897 		// Brechpunkte Aktualisieren...
898 		// keine Sonderbehandlung fuer EditEngine-CTOR ( Erste-Zeile-Problem ),
899 		// da in diesem Moment noch keine BreakPoints.
900 		// +1: Basic-Zeilen beginnen bei 1!
901 		pModulWindow->GetBreakPoints().AdjustBreakPoints( (sal_uInt16)nPara+1, bInserted );
902 
903 		// Im BreakPointWindow invalidieren...
904 		long nLineHeight = GetTextHeight();
905 		Size aSz = pModulWindow->GetBreakPointWindow().GetOutputSize();
906 		Rectangle aInvRec( Point( 0, 0 ), aSz );
907 		long nY = nPara*nLineHeight - pModulWindow->GetBreakPointWindow().GetCurYOffset();
908 		aInvRec.Top() = nY;
909 		pModulWindow->GetBreakPointWindow().Invalidate( aInvRec );
910 
911 		if ( bDoSyntaxHighlight )
912 		{
913 			String aDummy;
914 			aHighlighter.notifyChange( nPara, bInserted ? 1 : (-1), &aDummy, 1 );
915 		}
916 	}
917 }
918 
919 void EditorWindow::CreateProgress( const String& rText, sal_uLong nRange )
920 {
921 	DBG_ASSERT( !pProgress, "ProgressInfo existiert schon" );
922 	pProgress = new ProgressInfo( IDE_DLL()->GetShell()->GetViewFrame()->GetObjectShell(), rText, nRange );
923 }
924 
925 void EditorWindow::DestroyProgress()
926 {
927 	DELETEZ( pProgress );
928 }
929 
930 void EditorWindow::ForceSyntaxTimeout()
931 {
932 	aSyntaxIdleTimer.Stop();
933 	((Link&)aSyntaxIdleTimer.GetTimeoutHdl()).Call( &aSyntaxIdleTimer );
934 }
935 
936 
937 
938 BreakPointWindow::BreakPointWindow( Window* pParent ) :
939 	Window( pParent, WB_BORDER )
940 {
941 	pModulWindow = 0;
942 	nCurYOffset = 0;
943     setBackgroundColor(GetSettings().GetStyleSettings().GetFieldColor());
944     m_bHighContrastMode = GetSettings().GetStyleSettings().GetHighContrastMode();
945 	nMarkerPos = MARKER_NOMARKER;
946 
947 	// nCurYOffset merken und nicht von EditEngine holen.
948 	// Falls in EditEngine autom. gescrollt wurde, wuesste ich sonst nicht,
949 	// wo ich gerade stehe.
950 
951 	SetHelpId( HID_BASICIDE_BREAKPOINTWINDOW );
952 }
953 
954 
955 
956 __EXPORT BreakPointWindow::~BreakPointWindow()
957 {
958 }
959 
960 
961 
962 void __EXPORT BreakPointWindow::Resize()
963 {
964 ///	Invalidate();
965 }
966 
967 
968 
969 void __EXPORT BreakPointWindow::Paint( const Rectangle& )
970 {
971 	if ( SyncYOffset() )
972 		return;
973 
974 	Size aOutSz( GetOutputSize() );
975 	long nLineHeight = GetTextHeight();
976 
977 	Image aBrk1(((ModulWindowLayout *) pModulWindow->GetLayoutWindow())->
978                 getImage(IMGID_BRKENABLED, m_bHighContrastMode));
979 	Image aBrk0(((ModulWindowLayout *) pModulWindow->GetLayoutWindow())->
980                 getImage(IMGID_BRKDISABLED, m_bHighContrastMode));
981 	Size aBmpSz( aBrk1.GetSizePixel() );
982 	aBmpSz = PixelToLogic( aBmpSz );
983 	Point aBmpOff( 0, 0 );
984 	aBmpOff.X() = ( aOutSz.Width() - aBmpSz.Width() ) / 2;
985 	aBmpOff.Y() = ( nLineHeight - aBmpSz.Height() ) / 2;
986 
987 	BreakPoint* pBrk = GetBreakPoints().First();
988 	while ( pBrk )
989 	{
990 		sal_uLong nLine = pBrk->nLine-1;
991 		sal_uLong nY = nLine*nLineHeight - nCurYOffset;
992 		DrawImage( Point( 0, nY ) + aBmpOff, pBrk->bEnabled ? aBrk1 : aBrk0 );
993 		pBrk = GetBreakPoints().Next();
994 	}
995 	ShowMarker( sal_True );
996 }
997 
998 
999 
1000 void BreakPointWindow::DoScroll( long nHorzScroll, long nVertScroll )
1001 {
1002 	nCurYOffset -= nVertScroll;
1003 	Window::Scroll( nHorzScroll, nVertScroll );
1004 }
1005 
1006 
1007 
1008 void BreakPointWindow::SetMarkerPos( sal_uInt16 nLine, sal_Bool bError )
1009 {
1010 	if ( SyncYOffset() )
1011 		Update();
1012 
1013 	ShowMarker( sal_False );	// Alten wegzeichen...
1014 	nMarkerPos = nLine;
1015 	bErrorMarker = bError;
1016 	ShowMarker( sal_True );		// Neuen zeichnen...
1017 }
1018 
1019 void BreakPointWindow::ShowMarker( sal_Bool bShow )
1020 {
1021 	if ( nMarkerPos == MARKER_NOMARKER )
1022 		return;
1023 
1024 	Size aOutSz( GetOutputSize() );
1025 	long nLineHeight = GetTextHeight();
1026 
1027 	Image aMarker(((ModulWindowLayout*)pModulWindow->GetLayoutWindow())->
1028                   getImage(bErrorMarker
1029                            ? IMGID_ERRORMARKER : IMGID_STEPMARKER,
1030                            m_bHighContrastMode));
1031 
1032 	Size aMarkerSz( aMarker.GetSizePixel() );
1033 	aMarkerSz = PixelToLogic( aMarkerSz );
1034 	Point aMarkerOff( 0, 0 );
1035 	aMarkerOff.X() = ( aOutSz.Width() - aMarkerSz.Width() ) / 2;
1036 	aMarkerOff.Y() = ( nLineHeight - aMarkerSz.Height() ) / 2;
1037 
1038 	sal_uLong nY = nMarkerPos*nLineHeight - nCurYOffset;
1039 	Point aPos( 0, nY );
1040 	aPos += aMarkerOff;
1041 	if ( bShow )
1042 		DrawImage( aPos, aMarker );
1043 	else
1044 		Invalidate( Rectangle( aPos, aMarkerSz ) );
1045 }
1046 
1047 
1048 
1049 
1050 BreakPoint*	BreakPointWindow::FindBreakPoint( const Point& rMousePos )
1051 {
1052 	long nLineHeight = GetTextHeight();
1053 	long nYPos = rMousePos.Y() + nCurYOffset;
1054 //	Image aBrk( ((ModulWindowLayout*)pModulWindow->GetLayoutWindow())->GetImage( IMGID_BRKENABLED ) );
1055 //	Size aBmpSz( aBrk.GetSizePixel() );
1056 //	aBmpSz = PixelToLogic( aBmpSz );
1057 
1058 	BreakPoint* pBrk = GetBreakPoints().First();
1059 	while ( pBrk )
1060 	{
1061 		sal_uLong nLine = pBrk->nLine-1;
1062 		long nY = nLine*nLineHeight;
1063 		if ( ( nYPos > nY ) && ( nYPos < ( nY + nLineHeight ) ) )
1064 			return pBrk;
1065 		pBrk = GetBreakPoints().Next();
1066 	}
1067 	return 0;
1068 }
1069 
1070 void __EXPORT BreakPointWindow::MouseButtonDown( const MouseEvent& rMEvt )
1071 {
1072 	if ( rMEvt.GetClicks() == 2 )
1073 	{
1074 		Point aMousePos( PixelToLogic( rMEvt.GetPosPixel() ) );
1075 		long nLineHeight = GetTextHeight();
1076 		long nYPos = aMousePos.Y() + nCurYOffset;
1077 		long nLine = nYPos / nLineHeight + 1;
1078 		pModulWindow->ToggleBreakPoint( (sal_uLong)nLine );
1079 		// vielleicht mal etwas genauer...
1080 		Invalidate();
1081 	}
1082 }
1083 
1084 
1085 
1086 void __EXPORT BreakPointWindow::Command( const CommandEvent& rCEvt )
1087 {
1088 	if ( rCEvt.GetCommand() == COMMAND_CONTEXTMENU )
1089 	{
1090 		Point aPos( rCEvt.IsMouseEvent() ? rCEvt.GetMousePosPixel() : Point(1,1) );
1091 		Point aEventPos( PixelToLogic( aPos ) );
1092 		BreakPoint* pBrk = rCEvt.IsMouseEvent() ? FindBreakPoint( aEventPos ) : 0;
1093 		if ( pBrk )
1094 		{
1095 			// prueffen, ob Brechpunkt enabled....
1096 			PopupMenu aBrkPropMenu( IDEResId( RID_POPUP_BRKPROPS ) );
1097 			aBrkPropMenu.CheckItem( RID_ACTIV, pBrk->bEnabled );
1098 			switch ( aBrkPropMenu.Execute( this, aPos ) )
1099 			{
1100 				case RID_ACTIV:
1101 				{
1102 					pBrk->bEnabled = pBrk->bEnabled ? sal_False : sal_True;
1103 					pModulWindow->UpdateBreakPoint( *pBrk );
1104 					Invalidate();
1105 				}
1106 				break;
1107 				case RID_BRKPROPS:
1108 				{
1109 					BreakPointDialog aBrkDlg( this, GetBreakPoints() );
1110 					aBrkDlg.SetCurrentBreakPoint( pBrk );
1111 					aBrkDlg.Execute();
1112 					Invalidate();
1113 				}
1114 				break;
1115 			}
1116 		}
1117 		else
1118 		{
1119 			PopupMenu aBrkListMenu( IDEResId( RID_POPUP_BRKDLG ) );
1120 			switch ( aBrkListMenu.Execute( this, aPos ) )
1121 			{
1122 				case RID_BRKDLG:
1123 				{
1124 					BreakPointDialog aBrkDlg( this, GetBreakPoints() );
1125 					aBrkDlg.Execute();
1126 					Invalidate();
1127 				}
1128 				break;
1129 			}
1130 		}
1131 	}
1132 }
1133 
1134 sal_Bool BreakPointWindow::SyncYOffset()
1135 {
1136 	TextView* pView = pModulWindow->GetEditView();
1137 	if ( pView )
1138 	{
1139 		long nViewYOffset = pView->GetStartDocPos().Y();
1140 		if ( nCurYOffset != nViewYOffset )
1141 		{
1142 			nCurYOffset = nViewYOffset;
1143 			Invalidate();
1144 			return sal_True;
1145 		}
1146 	}
1147 	return sal_False;
1148 }
1149 
1150 // virtual
1151 void BreakPointWindow::DataChanged(DataChangedEvent const & rDCEvt)
1152 {
1153     Window::DataChanged(rDCEvt);
1154     if (rDCEvt.GetType() == DATACHANGED_SETTINGS
1155         && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
1156     {
1157         Color aColor(GetSettings().GetStyleSettings().GetFieldColor());
1158         if (aColor
1159             != rDCEvt.GetOldSettings()->GetStyleSettings().GetFieldColor())
1160         {
1161             setBackgroundColor(aColor);
1162             m_bHighContrastMode = GetSettings().GetStyleSettings().GetHighContrastMode();
1163             Invalidate();
1164         }
1165     }
1166 }
1167 
1168 void BreakPointWindow::setBackgroundColor(Color aColor)
1169 {
1170 	SetBackground(Wallpaper(aColor));
1171 }
1172 
1173 
1174 const sal_uInt16 ITEM_ID_VARIABLE = 1;
1175 const sal_uInt16 ITEM_ID_VALUE = 2;
1176 const sal_uInt16 ITEM_ID_TYPE = 3;
1177 
1178 WatchWindow::WatchWindow( Window* pParent ) :
1179 	BasicDockingWindow( pParent ),
1180 	aWatchStr( IDEResId( RID_STR_REMOVEWATCH ) ),
1181 	aXEdit( this, IDEResId( RID_EDT_WATCHEDIT ) ),
1182 	aRemoveWatchButton( this, IDEResId( RID_IMGBTN_REMOVEWATCH ) ),
1183 	aTreeListBox( this, WB_BORDER | WB_3DLOOK | WB_HASBUTTONS | WB_HASLINES | WB_HSCROLL | WB_TABSTOP
1184 								  | WB_HASLINESATROOT | WB_HASBUTTONSATROOT ),
1185 	aHeaderBar( this, WB_BUTTONSTYLE | WB_BORDER )
1186 {
1187 	aXEdit.SetAccessibleName(String(IDEResId( RID_STR_WATCHNAME)));
1188 	aTreeListBox.SetAccessibleName(String(IDEResId(RID_STR_WATCHNAME)));
1189 
1190 	nVirtToolBoxHeight = aXEdit.GetSizePixel().Height() + 7;
1191 	nHeaderBarHeight = 16;
1192 
1193     aTreeListBox.SetHelpId(HID_BASICIDE_WATCHWINDOW_LIST);
1194 	aTreeListBox.EnableInplaceEditing( sal_True );
1195 	aTreeListBox.SetSelectHdl( LINK( this, WatchWindow, TreeListHdl ) );
1196 	aTreeListBox.SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight + nHeaderBarHeight ) );
1197 	aTreeListBox.SetHighlightRange( 1, 5 );
1198 
1199 	Point aPnt( DWBORDER, nVirtToolBoxHeight + 1 );
1200 	aHeaderBar.SetPosPixel( aPnt );
1201 	aHeaderBar.SetEndDragHdl( LINK( this, WatchWindow, implEndDragHdl ) );
1202 
1203 	long nVarTabWidth = 220;
1204 	long nValueTabWidth = 100;
1205 	long nTypeTabWidth = 1250;
1206     aHeaderBar.InsertItem( ITEM_ID_VARIABLE, String( IDEResId( RID_STR_WATCHVARIABLE ) ), nVarTabWidth );
1207     aHeaderBar.InsertItem( ITEM_ID_VALUE, String( IDEResId( RID_STR_WATCHVALUE ) ), nValueTabWidth );
1208     aHeaderBar.InsertItem( ITEM_ID_TYPE, String( IDEResId( RID_STR_WATCHTYPE ) ), nTypeTabWidth );
1209 
1210     long tabs[ 4 ];
1211     tabs[ 0 ] = 3; // two tabs
1212     tabs[ 1 ] = 0;
1213     tabs[ 2 ] = nVarTabWidth;
1214     tabs[ 3 ] = nVarTabWidth + nValueTabWidth;
1215 	aTreeListBox.SvHeaderTabListBox::SetTabs( tabs, MAP_PIXEL );
1216 	aTreeListBox.InitHeaderBar( &aHeaderBar );
1217 
1218 	aTreeListBox.SetNodeDefaultImages( );
1219 
1220 	aHeaderBar.Show();
1221 
1222 	aRemoveWatchButton.Disable();
1223 
1224 	aTreeListBox.Show();
1225 
1226 	long nTextLen = GetTextWidth( aWatchStr ) + DWBORDER;
1227 	aXEdit.SetPosPixel( Point( nTextLen, 3 ) );
1228 	aXEdit.SetAccHdl( LINK( this, WatchWindow, EditAccHdl ) );
1229 	aXEdit.GetAccelerator().InsertItem( 1, KeyCode( KEY_RETURN ) );
1230 	aXEdit.GetAccelerator().InsertItem( 2, KeyCode( KEY_ESCAPE ) );
1231 	aXEdit.Show();
1232 
1233     aRemoveWatchButton.SetModeImage(Image(IDEResId(RID_IMG_REMOVEWATCH_HC)),
1234                                     BMP_COLOR_HIGHCONTRAST);
1235 	aRemoveWatchButton.SetClickHdl( LINK( this, WatchWindow, ButtonHdl ) );
1236 	aRemoveWatchButton.SetPosPixel( Point( nTextLen + aXEdit.GetSizePixel().Width() + 4, 2 ) );
1237 	Size aSz( aRemoveWatchButton.GetModeImage().GetSizePixel() );
1238 	aSz.Width() += 6;
1239 	aSz.Height() += 6;
1240 	aRemoveWatchButton.SetSizePixel( aSz );
1241 	aRemoveWatchButton.Show();
1242 
1243 	SetText( String( IDEResId( RID_STR_WATCHNAME ) ) );
1244 
1245 	SetHelpId( HID_BASICIDE_WATCHWINDOW );
1246 
1247 	// make watch window keyboard accessible
1248 	GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1249 }
1250 
1251 
1252 
1253 __EXPORT WatchWindow::~WatchWindow()
1254 {
1255 	GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1256 }
1257 
1258 
1259 
1260 void __EXPORT WatchWindow::Paint( const Rectangle& )
1261 {
1262 	DrawText( Point( DWBORDER, 7 ), aWatchStr );
1263 	lcl_DrawIDEWindowFrame( this );
1264 }
1265 
1266 
1267 
1268 void __EXPORT WatchWindow::Resize()
1269 {
1270 	Size aSz = GetOutputSizePixel();
1271 	Size aBoxSz( aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER );
1272 
1273 	if ( aBoxSz.Width() < 4 )	// < 4, weil noch Border...
1274 		aBoxSz.Width() = 0;
1275 	if ( aBoxSz.Height() < 4 )
1276 		aBoxSz.Height() = 0;
1277 
1278 	aBoxSz.Height() -= nHeaderBarHeight;
1279 	aTreeListBox.SetSizePixel( aBoxSz );
1280     aTreeListBox.GetHScroll()->SetPageSize( aTreeListBox.GetHScroll()->GetVisibleSize() );
1281 
1282 	aBoxSz.Height() = nHeaderBarHeight;
1283 	aHeaderBar.SetSizePixel( aBoxSz );
1284 
1285 	Invalidate();	//Wegen DrawLine im Paint...
1286 }
1287 
1288 struct MemberList
1289 {
1290 	String*			mpMemberNames;
1291 	int				mnMemberCount;
1292 
1293 	MemberList( void )
1294 		: mpMemberNames( NULL )
1295 		, mnMemberCount( 0 )
1296 	{}
1297 	~MemberList()
1298 	{
1299 		clear();
1300 	}
1301 
1302 	void clear( void );
1303 	void allocList( int nCount );
1304 };
1305 
1306 void MemberList::clear( void )
1307 {
1308 	if( mnMemberCount )
1309 	{
1310 		delete[] mpMemberNames;
1311 		mnMemberCount = 0;
1312 	}
1313 }
1314 
1315 void MemberList::allocList( int nCount )
1316 {
1317 	clear();
1318 	if( nCount > 0 )
1319 	{
1320 		mnMemberCount = nCount;
1321 		mpMemberNames = new String[ mnMemberCount ];
1322 	}
1323 }
1324 
1325 struct WatchItem
1326 {
1327     String          maName;
1328     String          maDisplayName;
1329     SbxObjectRef    mpObject;
1330 	MemberList		maMemberList;
1331 
1332     SbxDimArrayRef	mpArray;
1333 	int				nDimLevel;	// 0 = Root
1334 	int				nDimCount;
1335 	short*			pIndices;
1336 
1337 	WatchItem*		mpArrayParentItem;
1338 
1339     WatchItem( void )
1340 		: nDimLevel( 0 )
1341 		, nDimCount( 0 )
1342 		, pIndices( NULL )
1343 		, mpArrayParentItem( NULL )
1344     {}
1345     ~WatchItem()
1346 		{ clearWatchItem(); }
1347 
1348 	void clearWatchItem( bool bIncludeArrayData=true )
1349 	{
1350 		mpObject = NULL;
1351 		maMemberList.clear();
1352 		if( bIncludeArrayData )
1353 		{
1354 			mpArray = NULL;
1355 			nDimLevel = 0;
1356 			nDimCount = 0;
1357 			delete[] pIndices;
1358 			pIndices = NULL;
1359 		}
1360 	}
1361 
1362 	WatchItem* GetRootItem( void );
1363 	SbxDimArray* GetRootArray( void );
1364 };
1365 
1366 WatchItem* WatchItem::GetRootItem( void )
1367 {
1368 	WatchItem* pItem = mpArrayParentItem;
1369 	while( pItem )
1370 	{
1371 		if( pItem->mpArray.Is() )
1372 			break;
1373 		pItem = pItem->mpArrayParentItem;
1374 	}
1375 	return pItem;
1376 }
1377 
1378 SbxDimArray* WatchItem::GetRootArray( void )
1379 {
1380 	WatchItem* pRootItem = GetRootItem();
1381 	SbxDimArray* pRet = NULL;
1382 	if( pRootItem )
1383 		pRet = pRootItem->mpArray;
1384 	return pRet;
1385 }
1386 
1387 void WatchWindow::AddWatch( const String& rVName )
1388 {
1389 	WatchItem* pWatchItem = new WatchItem;
1390 	String aVar, aIndex;
1391 	lcl_SeparateNameAndIndex( rVName, aVar, aIndex );
1392 	pWatchItem->maName = aVar;
1393 
1394 	String aWatchStr_( aVar );
1395 	aWatchStr_ += String( RTL_CONSTASCII_USTRINGPARAM( "\t\t" ) );
1396 	SvLBoxEntry* pNewEntry = aTreeListBox.InsertEntry( aWatchStr_, 0, sal_True, LIST_APPEND );
1397 	pNewEntry->SetUserData( pWatchItem );
1398 
1399 	aTreeListBox.Select( pNewEntry, sal_True );
1400 	aTreeListBox.MakeVisible( pNewEntry );
1401 	aRemoveWatchButton.Enable();
1402 }
1403 
1404 sal_Bool WatchWindow::RemoveSelectedWatch()
1405 {
1406 	SvLBoxEntry* pEntry = aTreeListBox.GetCurEntry();
1407 	if ( pEntry )
1408 	{
1409 		aTreeListBox.GetModel()->Remove( pEntry );
1410 		pEntry = aTreeListBox.GetCurEntry();
1411 		if ( pEntry )
1412 			aXEdit.SetText( ((WatchItem*)pEntry->GetUserData())->maName );
1413 		else
1414 			aXEdit.SetText( String() );
1415 		if ( !aTreeListBox.GetEntryCount() )
1416 			aRemoveWatchButton.Disable();
1417 		return sal_True;
1418 	}
1419 	else
1420 		return sal_False;
1421 }
1422 
1423 
1424 IMPL_LINK_INLINE_START( WatchWindow, ButtonHdl, ImageButton *, pButton )
1425 {
1426 	if ( pButton == &aRemoveWatchButton )
1427 	{
1428         BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
1429         SfxViewFrame* pViewFrame = pIDEShell ? pIDEShell->GetViewFrame() : NULL;
1430 	    SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : NULL;
1431         if( pDispatcher )
1432 		{
1433 			pDispatcher->Execute( SID_BASICIDE_REMOVEWATCH );
1434 		}
1435 	}
1436 	return 0;
1437 }
1438 IMPL_LINK_INLINE_END( WatchWindow, ButtonHdl, ImageButton *, pButton )
1439 
1440 
1441 
1442 IMPL_LINK_INLINE_START( WatchWindow, TreeListHdl, SvTreeListBox *, EMPTYARG )
1443 {
1444 	SvLBoxEntry* pCurEntry = aTreeListBox.GetCurEntry();
1445 	if ( pCurEntry && pCurEntry->GetUserData() )
1446 		aXEdit.SetText( ((WatchItem*)pCurEntry->GetUserData())->maName );
1447 
1448 	return 0;
1449 }
1450 IMPL_LINK_INLINE_END( WatchWindow, TreeListHdl, SvTreeListBox *, EMPTYARG )
1451 
1452 
1453 IMPL_LINK_INLINE_START( WatchWindow, implEndDragHdl, HeaderBar *, pBar )
1454 {
1455 	(void)pBar;
1456 
1457     const sal_Int32 TAB_WIDTH_MIN = 10;
1458 	sal_Int32 nMaxWidth =
1459         aHeaderBar.GetSizePixel().getWidth() - 2 * TAB_WIDTH_MIN;
1460 
1461     sal_Int32 nVariableWith = aHeaderBar.GetItemSize( ITEM_ID_VARIABLE );
1462     if( nVariableWith < TAB_WIDTH_MIN )
1463         aHeaderBar.SetItemSize( ITEM_ID_VARIABLE, TAB_WIDTH_MIN );
1464     else if( nVariableWith > nMaxWidth )
1465         aHeaderBar.SetItemSize( ITEM_ID_VARIABLE, nMaxWidth );
1466 
1467     sal_Int32 nValueWith = aHeaderBar.GetItemSize( ITEM_ID_VALUE );
1468     if( nValueWith < TAB_WIDTH_MIN )
1469         aHeaderBar.SetItemSize( ITEM_ID_VALUE, TAB_WIDTH_MIN );
1470     else if( nValueWith > nMaxWidth )
1471         aHeaderBar.SetItemSize( ITEM_ID_VALUE, nMaxWidth );
1472 
1473     if (aHeaderBar.GetItemSize( ITEM_ID_TYPE ) < TAB_WIDTH_MIN)
1474         aHeaderBar.SetItemSize( ITEM_ID_TYPE, TAB_WIDTH_MIN );
1475 
1476     sal_Int32 nPos = 0;
1477 	sal_uInt16 nTabs = aHeaderBar.GetItemCount();
1478     // OSL_ASSERT( m_treelb->TabCount() == nTabs );
1479 	for( sal_uInt16 i = 1 ; i < nTabs ; ++i )
1480 	{
1481 		nPos += aHeaderBar.GetItemSize( i );
1482 		aTreeListBox.SetTab( i, nPos, MAP_PIXEL );
1483 	}
1484 	return 0;
1485 }
1486 IMPL_LINK_INLINE_END( WatchWindow, implEndDragHdl, HeaderBar *, pBar )
1487 
1488 
1489 IMPL_LINK( WatchWindow, EditAccHdl, Accelerator *, pAcc )
1490 {
1491 	switch ( pAcc->GetCurKeyCode().GetCode() )
1492 	{
1493 		case KEY_RETURN:
1494 		{
1495 			String aCurText( aXEdit.GetText() );
1496 			if ( aCurText.Len() )
1497 			{
1498 				AddWatch( aCurText );
1499 				aXEdit.SetSelection( Selection( 0, 0xFFFF ) );
1500 				UpdateWatches();
1501 			}
1502 			else
1503 				Sound::Beep();
1504 		}
1505 		break;
1506 		case KEY_ESCAPE:
1507 		{
1508 			aXEdit.SetText( String() );
1509 		}
1510 		break;
1511 	}
1512 
1513 	return 0;
1514 }
1515 
1516 void WatchWindow::UpdateWatches( bool bBasicStopped )
1517 {
1518 	aTreeListBox.UpdateWatches( bBasicStopped );
1519 }
1520 
1521 
1522 StackWindow::StackWindow( Window* pParent ) :
1523 	BasicDockingWindow( pParent ),
1524 	aTreeListBox( this, WB_BORDER | WB_3DLOOK | WB_HSCROLL | WB_TABSTOP ),
1525 	aGotoCallButton( this, IDEResId( RID_IMGBTN_GOTOCALL ) ),
1526 	aStackStr( IDEResId( RID_STR_STACK ) )
1527 {
1528    	aTreeListBox.SetHelpId(HID_BASICIDE_STACKWINDOW_LIST);
1529 	aTreeListBox.SetAccessibleName(String( IDEResId(RID_STR_STACKNAME)));
1530 	aTreeListBox.SetPosPixel( Point( DWBORDER, nVirtToolBoxHeight ) );
1531 	aTreeListBox.SetHighlightRange();
1532     aTreeListBox.SetSelectionMode( NO_SELECTION );
1533     aTreeListBox.InsertEntry( String(), 0, sal_False, LIST_APPEND );
1534 	aTreeListBox.Show();
1535 
1536 	SetText( String( IDEResId( RID_STR_STACKNAME ) ) );
1537 
1538 	SetHelpId( HID_BASICIDE_STACKWINDOW );
1539 
1540 	aGotoCallButton.SetClickHdl( LINK( this, StackWindow, ButtonHdl ) );
1541 	aGotoCallButton.SetPosPixel( Point( DWBORDER, 2 ) );
1542 	Size aSz( aGotoCallButton.GetModeImage().GetSizePixel() );
1543 	aSz.Width() += 6;
1544 	aSz.Height() += 6;
1545 	aGotoCallButton.SetSizePixel( aSz );
1546 //	aGotoCallButton.Show();	// wird vom Basic noch nicht unterstuetzt!
1547 	aGotoCallButton.Hide();
1548 
1549 	// make stack window keyboard accessible
1550 	GetSystemWindow()->GetTaskPaneList()->AddWindow( this );
1551 }
1552 
1553 
1554 
1555 __EXPORT StackWindow::~StackWindow()
1556 {
1557 	GetSystemWindow()->GetTaskPaneList()->RemoveWindow( this );
1558 }
1559 
1560 
1561 
1562 void __EXPORT StackWindow::Paint( const Rectangle& )
1563 {
1564 	DrawText( Point( DWBORDER, 7 ), aStackStr );
1565 	lcl_DrawIDEWindowFrame( this );
1566 }
1567 
1568 
1569 
1570 void __EXPORT StackWindow::Resize()
1571 {
1572 	Size aSz = GetOutputSizePixel();
1573 	Size aBoxSz( aSz.Width() - 2*DWBORDER, aSz.Height() - nVirtToolBoxHeight - DWBORDER );
1574 
1575 	if ( aBoxSz.Width() < 4 )	// < 4, weil noch Border...
1576 		aBoxSz.Width() = 0;
1577 	if ( aBoxSz.Height() < 4 )
1578 		aBoxSz.Height() = 0;
1579 
1580 	aTreeListBox.SetSizePixel( aBoxSz );
1581 
1582 	Invalidate();	//Wegen DrawLine im Paint...
1583 }
1584 
1585 
1586 
1587 IMPL_LINK_INLINE_START( StackWindow, ButtonHdl, ImageButton *, pButton )
1588 {
1589 	if ( pButton == &aGotoCallButton )
1590 	{
1591         BasicIDEShell* pIDEShell = IDE_DLL()->GetShell();
1592         SfxViewFrame* pViewFrame = pIDEShell ? pIDEShell->GetViewFrame() : NULL;
1593 	    SfxDispatcher* pDispatcher = pViewFrame ? pViewFrame->GetDispatcher() : NULL;
1594         if( pDispatcher )
1595 		{
1596 			pDispatcher->Execute( SID_BASICIDE_GOTOCALL );
1597 		}
1598 	}
1599 	return 0;
1600 }
1601 IMPL_LINK_INLINE_END( StackWindow, ButtonHdl, ImageButton *, pButton )
1602 
1603 
1604 
1605 void __EXPORT StackWindow::UpdateCalls()
1606 {
1607 	aTreeListBox.SetUpdateMode( sal_False );
1608 	aTreeListBox.Clear();
1609 
1610     if ( StarBASIC::IsRunning() )
1611     {
1612 	    SbxError eOld = SbxBase::GetError();
1613         aTreeListBox.SetSelectionMode( SINGLE_SELECTION );
1614 
1615 	    sal_uInt16 nScope = 0;
1616 	    SbMethod* pMethod = StarBASIC::GetActiveMethod( nScope );
1617 	    while ( pMethod )
1618 	    {
1619 		    String aEntry( String::CreateFromInt32(nScope ));
1620 		    if ( aEntry.Len() < 2 )
1621 			    aEntry.Insert( ' ', 0 );
1622 		    aEntry += String( RTL_CONSTASCII_USTRINGPARAM( ": " ) );
1623 		    aEntry += pMethod->GetName();
1624 		    SbxArray* pParams = pMethod->GetParameters();
1625 		    SbxInfo* pInfo = pMethod->GetInfo();
1626 		    if ( pParams )
1627 		    {
1628 			    aEntry += '(';
1629 			    // 0 ist der Name der Sub...
1630 			    for ( sal_uInt16 nParam = 1; nParam < pParams->Count(); nParam++ )
1631 			    {
1632 				    SbxVariable* pVar = pParams->Get( nParam );
1633 				    DBG_ASSERT( pVar, "Parameter?!" );
1634 				    if ( pVar->GetName().Len() )
1635 					    aEntry += pVar->GetName();
1636 				    else if ( pInfo )
1637 				    {
1638 					    const SbxParamInfo* pParam = pInfo->GetParam( nParam );
1639 					    if ( pParam )
1640 						    aEntry += pParam->aName;
1641 				    }
1642 				    aEntry += '=';
1643 					SbxDataType eType = pVar->GetType();
1644 	    			if( eType & SbxARRAY )
1645 					    aEntry += String( RTL_CONSTASCII_USTRINGPARAM( "..." ) );
1646 				    else if( eType != SbxOBJECT )
1647 					    aEntry += pVar->GetString();
1648 				    if ( nParam < ( pParams->Count() - 1 ) )
1649 					    aEntry += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) );
1650 			    }
1651 			    aEntry += ')';
1652 		    }
1653 		    aTreeListBox.InsertEntry( aEntry, 0, sal_False, LIST_APPEND );
1654 		    nScope++;
1655 		    pMethod = StarBASIC::GetActiveMethod( nScope );
1656 	    }
1657 
1658 	    SbxBase::ResetError();
1659 	    if( eOld != SbxERR_OK )
1660 		    SbxBase::SetError( eOld );
1661     }
1662     else
1663     {
1664         aTreeListBox.SetSelectionMode( NO_SELECTION );
1665         aTreeListBox.InsertEntry( String(), 0, sal_False, LIST_APPEND );
1666     }
1667 
1668 	aTreeListBox.SetUpdateMode( sal_True );
1669 }
1670 
1671 
1672 
1673 
1674 ComplexEditorWindow::ComplexEditorWindow( ModulWindow* pParent ) :
1675 	Window( pParent, WB_3DLOOK | WB_CLIPCHILDREN ),
1676 	aBrkWindow( this ),
1677 	aEdtWindow( this ),
1678 	aEWVScrollBar( this, WB_VSCROLL | WB_DRAG )
1679 {
1680 	aEdtWindow.SetModulWindow( pParent );
1681 	aBrkWindow.SetModulWindow( pParent );
1682 	aEdtWindow.Show();
1683 	aBrkWindow.Show();
1684 
1685 	aEWVScrollBar.SetLineSize( SCROLL_LINE );
1686 	aEWVScrollBar.SetPageSize( SCROLL_PAGE );
1687 	aEWVScrollBar.SetScrollHdl( LINK( this, ComplexEditorWindow, ScrollHdl ) );
1688 	aEWVScrollBar.Show();
1689 }
1690 
1691 
1692 
1693 void __EXPORT ComplexEditorWindow::Resize()
1694 {
1695 	Size aOutSz = GetOutputSizePixel();
1696 	Size aSz( aOutSz );
1697 	aSz.Width() -= 2*DWBORDER;
1698 	aSz.Height() -= 2*DWBORDER;
1699 	long nBrkWidth = 20;
1700 	long nSBWidth = aEWVScrollBar.GetSizePixel().Width();
1701 
1702 	Size aBrkSz( Size( nBrkWidth, aSz.Height() ) );
1703 	aBrkWindow.SetPosSizePixel( Point( DWBORDER, DWBORDER ), aBrkSz );
1704 
1705     Size aEWSz( Size( aSz.Width() - nBrkWidth - nSBWidth + 2, aSz.Height() ) );
1706 	aEdtWindow.SetPosSizePixel( Point( DWBORDER+aBrkSz.Width()-1, DWBORDER ), aEWSz );
1707 
1708 	aEWVScrollBar.SetPosSizePixel( Point( aOutSz.Width()-DWBORDER-nSBWidth, DWBORDER ), Size( nSBWidth, aSz.Height() ) );
1709 
1710 	// Macht das EditorWindow, ausserdem hier falsch, da Pixel
1711 //	aEWVScrollBar.SetPageSize( aEWSz.Height() * 8 / 10 );
1712 //	aEWVScrollBar.SetVisibleSize( aSz.Height() );
1713 //	Invalidate();
1714 }
1715 
1716 IMPL_LINK( ComplexEditorWindow, ScrollHdl, ScrollBar *, pCurScrollBar )
1717 {
1718 	if ( aEdtWindow.GetEditView() )
1719 	{
1720 		DBG_ASSERT( pCurScrollBar == &aEWVScrollBar, "Wer scrollt hier ?" );
1721 		long nDiff = aEdtWindow.GetEditView()->GetStartDocPos().Y() - pCurScrollBar->GetThumbPos();
1722 		aEdtWindow.GetEditView()->Scroll( 0, nDiff );
1723 		aBrkWindow.DoScroll( 0, nDiff );
1724 		aEdtWindow.GetEditView()->ShowCursor( sal_False, sal_True );
1725 		pCurScrollBar->SetThumbPos( aEdtWindow.GetEditView()->GetStartDocPos().Y() );
1726 	}
1727 
1728 	return 0;
1729 }
1730 
1731 // virtual
1732 void ComplexEditorWindow::DataChanged(DataChangedEvent const & rDCEvt)
1733 {
1734     Window::DataChanged(rDCEvt);
1735     if (rDCEvt.GetType() == DATACHANGED_SETTINGS
1736         && (rDCEvt.GetFlags() & SETTINGS_STYLE) != 0)
1737     {
1738         Color aColor(GetSettings().GetStyleSettings().GetFaceColor());
1739         if (aColor
1740             != rDCEvt.GetOldSettings()->GetStyleSettings().GetFaceColor())
1741         {
1742             SetBackground(Wallpaper(aColor));
1743             Invalidate();
1744         }
1745     }
1746 }
1747 
1748 // virtual
1749 uno::Reference< awt::XWindowPeer >
1750 EditorWindow::GetComponentInterface(sal_Bool bCreate)
1751 {
1752     uno::Reference< awt::XWindowPeer > xPeer(
1753         Window::GetComponentInterface(false));
1754     if (!xPeer.is() && bCreate)
1755     {
1756         // Make sure edit engine and view are available:
1757         if (!pEditEngine)
1758             CreateEditEngine();
1759 
1760         xPeer = new ::svt::TextWindowPeer(*GetEditView());
1761         SetComponentInterface(xPeer);
1762     }
1763     return xPeer;
1764 }
1765 
1766 WatchTreeListBox::WatchTreeListBox( Window* pParent, WinBits nWinBits )
1767 	: SvHeaderTabListBox( pParent, nWinBits )
1768 {}
1769 
1770 WatchTreeListBox::~WatchTreeListBox()
1771 {
1772 	// User-Daten zerstoeren...
1773 	SvLBoxEntry* pEntry = First();
1774 	while ( pEntry )
1775 	{
1776 		delete (WatchItem*)pEntry->GetUserData();
1777 		pEntry = Next( pEntry );
1778 	}
1779 }
1780 
1781 void WatchTreeListBox::SetTabs()
1782 {
1783 	SvHeaderTabListBox::SetTabs();
1784 	sal_uInt16 nTabCount_ = aTabs.Count();
1785 	for( sal_uInt16 i = 0 ; i < nTabCount_ ; i++ )
1786 	{
1787 		SvLBoxTab* pTab = (SvLBoxTab*)aTabs.GetObject(i);
1788 		if( i == 2 )
1789 			pTab->nFlags |= SV_LBOXTAB_EDITABLE;
1790 		else
1791 			pTab->nFlags &= ~SV_LBOXTAB_EDITABLE;
1792 	}
1793 }
1794 
1795 void WatchTreeListBox::RequestingChilds( SvLBoxEntry * pParent )
1796 {
1797 	if( !StarBASIC::IsRunning() )
1798         return;
1799 
1800     if( GetChildCount( pParent ) > 0 )
1801         return;
1802 
1803 	SvLBoxEntry * pEntry = pParent;
1804     WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
1805 
1806 	SbxDimArray* pArray = pItem->mpArray;
1807 	SbxDimArray* pRootArray = pItem->GetRootArray();
1808 	bool bArrayIsRootArray = false;
1809 	if( !pArray && pRootArray )
1810 	{
1811 		pArray = pRootArray;
1812 		bArrayIsRootArray = true;
1813 	}
1814 
1815     SbxObject* pObj = pItem->mpObject;
1816     if( pObj )
1817     {
1818 		createAllObjectProperties( pObj );
1819  	    SbxArray* pProps = pObj->GetProperties();
1820 	    sal_uInt16 nPropCount = pProps->Count();
1821 		pItem->maMemberList.allocList( nPropCount );
1822 
1823 	    for( sal_uInt16 i = 0 ; i < nPropCount - 3 ; i++ )
1824 	    {
1825 		    SbxVariable* pVar = pProps->Get( i );
1826 
1827             String aName( pVar->GetName() );
1828 			pItem->maMemberList.mpMemberNames[i] = aName;
1829             SvLBoxEntry* pChildEntry = SvTreeListBox::InsertEntry( aName, pEntry );
1830             WatchItem* pChildItem = new WatchItem();
1831 			pChildItem->maName = aName;
1832 	        pChildEntry->SetUserData( pChildItem );
1833 	    }
1834 		if( nPropCount > 0 )
1835 		{
1836 			UpdateWatches();
1837 		}
1838     }
1839 	else if( pArray )
1840 	{
1841 	    sal_uInt16 nElementCount = 0;
1842 
1843 		// Loop through indices of current level
1844 		int nParentLevel = bArrayIsRootArray ? pItem->nDimLevel : 0;
1845 		int nThisLevel = nParentLevel + 1;
1846 		sal_Int32 nMin, nMax;
1847 		pArray->GetDim32( nThisLevel, nMin, nMax );
1848 		for( sal_Int32 i = nMin ; i <= nMax ; i++ )
1849 		{
1850             WatchItem* pChildItem = new WatchItem();
1851 
1852 			// Copy data and create name
1853             String aBaseName( pItem->maName );
1854 			pChildItem->maName = aBaseName;
1855 
1856 			String aIndexStr = String( RTL_CONSTASCII_USTRINGPARAM( "(" ) );
1857 			// pChildItem->mpArray = pItem->mpArray;
1858 			pChildItem->mpArrayParentItem = pItem;
1859 			pChildItem->nDimLevel = nThisLevel;
1860 			pChildItem->nDimCount = pItem->nDimCount;
1861 			pChildItem->pIndices = new short[ pChildItem->nDimCount ];
1862 			sal_uInt16 j;
1863 			for( j = 0 ; j < nParentLevel ; j++ )
1864 			{
1865 				short n = pChildItem->pIndices[j] = pItem->pIndices[j];
1866 				aIndexStr += String::CreateFromInt32( n );
1867 				aIndexStr += String( RTL_CONSTASCII_USTRINGPARAM( "," ) );
1868 			}
1869 			pChildItem->pIndices[ nParentLevel ] = sal::static_int_cast<short>( i );
1870 			aIndexStr += String::CreateFromInt32( i );
1871 			aIndexStr += String( RTL_CONSTASCII_USTRINGPARAM( ")" ) );
1872 
1873 			String aDisplayName;
1874 			WatchItem* pArrayRootItem = pChildItem->GetRootItem();
1875 			if( pArrayRootItem && pArrayRootItem->mpArrayParentItem )
1876 				aDisplayName = pItem->maDisplayName;
1877 			else
1878 				aDisplayName = aBaseName;
1879 			aDisplayName += aIndexStr;
1880 			pChildItem->maDisplayName = aDisplayName;
1881 
1882             SvLBoxEntry* pChildEntry = SvTreeListBox::InsertEntry( aDisplayName, pEntry );
1883 			nElementCount++;
1884 			pChildEntry->SetUserData( pChildItem );
1885 		}
1886 		if( nElementCount > 0 )
1887 		{
1888 			UpdateWatches();
1889 		}
1890 	}
1891 }
1892 
1893 SbxBase* WatchTreeListBox::ImplGetSBXForEntry( SvLBoxEntry* pEntry, bool& rbArrayElement )
1894 {
1895 	SbxBase* pSBX = NULL;
1896 	rbArrayElement = false;
1897 
1898     WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
1899 	String aVName( pItem->maName );
1900 
1901     SvLBoxEntry* pParentEntry = GetParent( pEntry );
1902 	WatchItem* pParentItem = pParentEntry ? (WatchItem*)pParentEntry->GetUserData() : NULL;
1903     if( pParentItem )
1904     {
1905         SbxObject* pObj = pParentItem->mpObject;
1906         SbxDimArray* pArray;
1907         if( pObj )
1908 		{
1909     		pSBX = pObj->Find( aVName, SbxCLASS_DONTCARE );
1910 
1911 			SbxVariable* pVar;
1912 			if ( pSBX && (pVar = PTR_CAST( SbxVariable, pSBX )) != NULL
1913 						&& !pSBX->ISA( SbxMethod ) )
1914 			{
1915 				// Force getting value
1916 				SbxValues aRes;
1917 				aRes.eType = SbxVOID;
1918 				pVar->Get( aRes );
1919 			}
1920 		}
1921 		// Array?
1922 		else if( (pArray = pItem->GetRootArray()) != NULL )
1923 		// else if( (pArray = pItem->mpArray) != NULL )
1924 		{
1925 			rbArrayElement = true;
1926 			if( pParentItem->nDimLevel + 1 == pParentItem->nDimCount )
1927 			// if( pItem->nDimLevel == pItem->nDimCount )
1928 				pSBX = pArray->Get( pItem->pIndices );
1929 			// else
1930 				// pSBX = pArray;
1931 		}
1932     }
1933 	else
1934 	{
1935 		pSBX = StarBASIC::FindSBXInCurrentScope( aVName );
1936 	}
1937 	return pSBX;
1938 }
1939 
1940 sal_Bool __EXPORT WatchTreeListBox::EditingEntry( SvLBoxEntry* pEntry, Selection& )
1941 {
1942     WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
1943 
1944 	sal_Bool bEdit = sal_False;
1945 	if ( StarBASIC::IsRunning() && StarBASIC::GetActiveMethod() && !SbxBase::IsError() )
1946 	{
1947 		// No out of scope entries
1948 		bool bArrayElement;
1949 		SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
1950 		if ( ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) ) || bArrayElement )
1951 		{
1952 			// Accept no objects and only end nodes of arrays for editing
1953 			if( !pItem->mpObject && (pItem->mpArray == NULL || pItem->nDimLevel == pItem->nDimCount) )
1954 			{
1955 				aEditingRes = SvHeaderTabListBox::GetEntryText( pEntry, ITEM_ID_VALUE-1 );
1956 				aEditingRes.EraseLeadingChars();
1957 				aEditingRes.EraseTrailingChars();
1958 				bEdit = sal_True;
1959 			}
1960 		}
1961 	}
1962 
1963 	if ( !bEdit )
1964 		Sound::Beep();
1965 
1966 	return bEdit;
1967 }
1968 
1969 sal_Bool __EXPORT WatchTreeListBox::EditedEntry( SvLBoxEntry* pEntry, const String& rNewText )
1970 {
1971     WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
1972 	String aVName( pItem->maName );
1973 
1974 	String aResult = rNewText;
1975 	aResult.EraseLeadingChars();
1976 	aResult.EraseTrailingChars();
1977 
1978 	sal_uInt16 nResultLen = aResult.Len();
1979 	sal_Unicode cFirst = aResult.GetChar( 0 );
1980 	sal_Unicode cLast  = aResult.GetChar( nResultLen - 1 );
1981 	if( cFirst == '\"' && cLast == '\"' )
1982 		aResult = aResult.Copy( 1, nResultLen - 2 );
1983 
1984 	sal_Bool bResModified = ( aResult != aEditingRes ) ? sal_True : sal_False;
1985 	sal_Bool bError = sal_False;
1986 	if ( !aVName.Len() )
1987 	{
1988 		bError = sal_True;
1989 	}
1990 
1991 	sal_Bool bRet = sal_False;
1992 
1993 	if ( bError )
1994 	{
1995 		Sound::Beep();
1996 	}
1997 	else if ( bResModified )
1998 	{
1999 		bRet = ImplBasicEntryEdited( pEntry, aResult );
2000 	}
2001 
2002 	return bRet;
2003 }
2004 
2005 sal_Bool WatchTreeListBox::ImplBasicEntryEdited( SvLBoxEntry* pEntry, const String& rResult )
2006 {
2007     WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
2008 	String aVName( pItem->maName );
2009 
2010 	sal_Bool bError = sal_False;
2011 	String aResult( rResult );
2012 	String aIndex;
2013 	bool bArrayElement;
2014 	SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
2015 
2016 	SbxBase* pToBeChanged = NULL;
2017 	if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) )
2018 	{
2019 		SbxVariable* pVar = (SbxVariable*)pSBX;
2020 		SbxDataType eType = pVar->GetType();
2021 		if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
2022 			bError = sal_True;
2023 		else if ( eType & SbxARRAY )
2024 			bError = sal_True;
2025 		else
2026 			pToBeChanged = pSBX;
2027 	}
2028 
2029 	if ( pToBeChanged )
2030 	{
2031 		if ( pToBeChanged->ISA( SbxVariable ) )
2032 		{
2033 			// Wenn der Typ variabel ist, macht die Konvertierung des SBX nichts,
2034 			// bei festem Typ wird der String konvertiert.
2035 			((SbxVariable*)pToBeChanged)->PutStringExt( aResult );
2036 		}
2037 		else
2038 			bError = sal_True;
2039 	}
2040 
2041 	// Wenn jemand z.B. einen zu grossen Wert fuer ein Int eingegeben hat,
2042 	// folgt beim naechsten Step() ein Runtime-Error.
2043 	if ( SbxBase::IsError() )
2044 	{
2045 		bError = sal_True;
2046 		SbxBase::ResetError();
2047 	}
2048 
2049 	if ( bError )
2050 		Sound::Beep();
2051 
2052 	UpdateWatches();
2053 
2054 	// Der Text soll niemals 1-zu-1 uebernommen werden, weil dann das
2055 	// UpdateWatches verlorengeht.
2056 	return sal_False;
2057 }
2058 
2059 
2060 static void implCollapseModifiedObjectEntry( SvLBoxEntry* pParent, WatchTreeListBox* pThis )
2061 {
2062 	pThis->Collapse( pParent );
2063 
2064 	SvLBoxTreeList*	pModel = pThis->GetModel();
2065 	SvLBoxEntry* pDeleteEntry;
2066 	while( (pDeleteEntry = pThis->SvTreeListBox::GetEntry( pParent, 0 )) != NULL )
2067 	{
2068 		implCollapseModifiedObjectEntry( pDeleteEntry, pThis );
2069 
2070         WatchItem* pItem = (WatchItem*)pDeleteEntry->GetUserData();
2071 		delete pItem;
2072         pModel->Remove( pDeleteEntry );
2073 	}
2074 }
2075 
2076 static String implCreateTypeStringForDimArray( WatchItem* pItem, SbxDataType eType )
2077 {
2078 	String aRetStr = getBasicTypeName( eType );
2079 
2080 	SbxDimArray* pArray = pItem->mpArray;
2081 	if( !pArray )
2082 		pArray = pItem->GetRootArray();
2083 	if( pArray )
2084 	{
2085 		int nDimLevel = pItem->nDimLevel;
2086 		int nDims = pItem->nDimCount;
2087 		if( nDimLevel < nDims )
2088 		{
2089 			aRetStr += '(';
2090 			for( int i = nDimLevel ; i < nDims ; i++ )
2091 			{
2092 				short nMin, nMax;
2093 				pArray->GetDim( sal::static_int_cast<short>( i+1 ), nMin, nMax );
2094 				aRetStr += String::CreateFromInt32( nMin );
2095 				aRetStr += String( RTL_CONSTASCII_USTRINGPARAM( " to " ) );
2096 				aRetStr += String::CreateFromInt32( nMax );
2097 				if( i < nDims - 1 )
2098 					aRetStr += String( RTL_CONSTASCII_USTRINGPARAM( ", " ) );
2099 			}
2100 			aRetStr += ')';
2101 		}
2102 	}
2103 	return aRetStr;
2104 }
2105 
2106 
2107 void implEnableChildren( SvLBoxEntry* pEntry, bool bEnable )
2108 // inline void implEnableChildren( SvLBoxEntry* pEntry, bool bEnable )
2109 {
2110 	if( bEnable )
2111 	{
2112 		pEntry->SetFlags(
2113 			(pEntry->GetFlags() &
2114 			~(SV_ENTRYFLAG_NO_NODEBMP | SV_ENTRYFLAG_HAD_CHILDREN))
2115 			| SV_ENTRYFLAG_CHILDS_ON_DEMAND );
2116 	}
2117 	else
2118 	{
2119 		pEntry->SetFlags(
2120 			(pEntry->GetFlags() & ~(SV_ENTRYFLAG_CHILDS_ON_DEMAND)) );
2121 	}
2122 }
2123 
2124 void WatchTreeListBox::UpdateWatches( bool bBasicStopped )
2125 {
2126 	SbMethod* pCurMethod = StarBASIC::GetActiveMethod();
2127 
2128 	SbxError eOld = SbxBase::GetError();
2129 	setBasicWatchMode( true );
2130 
2131 	SvLBoxEntry* pEntry = First();
2132 	while ( pEntry )
2133 	{
2134         WatchItem* pItem = (WatchItem*)pEntry->GetUserData();
2135 		String aVName( pItem->maName );
2136 		DBG_ASSERT( aVName.Len(), "Var? - Darf nicht leer sein!" );
2137 		String aWatchStr;
2138 		String aTypeStr;
2139 		if ( pCurMethod )
2140 		{
2141 			bool bArrayElement;
2142 			SbxBase* pSBX = ImplGetSBXForEntry( pEntry, bArrayElement );
2143 
2144 			// Array? If no end node create type string
2145 			if( bArrayElement && pItem->nDimLevel < pItem->nDimCount )
2146 			{
2147 				SbxDimArray* pRootArray = pItem->GetRootArray();
2148 				SbxDataType eType = pRootArray->GetType();
2149 				// SbxDataType eType = pItem->mpArray->GetType();
2150 				aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
2151 				implEnableChildren( pEntry, true );
2152 			}
2153 
2154 			bool bCollapse = false;
2155 			if ( pSBX && pSBX->ISA( SbxVariable ) && !pSBX->ISA( SbxMethod ) )
2156 			{
2157 				SbxVariable* pVar = (SbxVariable*)pSBX;
2158 				// Sonderbehandlung fuer Arrays:
2159 				SbxDataType eType = pVar->GetType();
2160 				if ( eType & SbxARRAY )
2161 				{
2162 					// Mehrdimensionale Arrays beruecksichtigen!
2163 					SbxBase* pBase = pVar->GetObject();
2164 					if ( pBase && pBase->ISA( SbxDimArray ) )
2165 					{
2166 						SbxDimArray* pNewArray = (SbxDimArray*)pBase;
2167 						SbxDimArray* pOldArray = pItem->mpArray;
2168 
2169 						bool bArrayChanged = false;
2170 						if( pNewArray != NULL && pOldArray != NULL )
2171 						{
2172 							// Compare Array dimensions to see if array has changed
2173 							// Can be a copy, so comparing pointers does not work
2174 							sal_uInt16 nOldDims = pOldArray->GetDims();
2175 							sal_uInt16 nNewDims = pNewArray->GetDims();
2176 							if( nOldDims != nNewDims )
2177 							{
2178 								bArrayChanged = true;
2179 							}
2180 							else
2181 							{
2182 								for( int i = 0 ; i < nOldDims ; i++ )
2183 								{
2184 									short nOldMin, nOldMax;
2185 									short nNewMin, nNewMax;
2186 
2187 									pOldArray->GetDim( sal::static_int_cast<short>( i+1 ), nOldMin, nOldMax );
2188 									pNewArray->GetDim( sal::static_int_cast<short>( i+1 ), nNewMin, nNewMax );
2189 									if( nOldMin != nNewMin || nOldMax != nNewMax )
2190 									{
2191 										bArrayChanged = true;
2192 										break;
2193 									}
2194 								}
2195 							}
2196 						}
2197 						else if( pNewArray == NULL || pOldArray == NULL )
2198 							bArrayChanged = true;
2199 
2200 						if( pNewArray )
2201 							implEnableChildren( pEntry, true );
2202 
2203 						// #i37227 Clear always and replace array
2204 						if( pNewArray != pOldArray )
2205 						{
2206 							pItem->clearWatchItem( false );
2207 							if( pNewArray )
2208 							{
2209 								implEnableChildren( pEntry, true );
2210 
2211 								pItem->mpArray = pNewArray;
2212 								sal_uInt16 nDims = pNewArray->GetDims();
2213 								pItem->nDimLevel = 0;
2214 								pItem->nDimCount = nDims;
2215 							}
2216 						}
2217 						if( bArrayChanged && pOldArray != NULL )
2218 							bCollapse = true;
2219 
2220 						aTypeStr = implCreateTypeStringForDimArray( pItem, eType );
2221 					}
2222 					else
2223 						aWatchStr += String( RTL_CONSTASCII_USTRINGPARAM( "<?>" ) );
2224 				}
2225 				else if ( (sal_uInt8)eType == (sal_uInt8)SbxOBJECT )
2226 				{
2227                     SbxObject* pObj = NULL;
2228 			        SbxBase* pBase = pVar->GetObject();
2229 			        if( pBase && pBase->ISA( SbxObject ) )
2230                         pObj = (SbxObject*)pBase;
2231 
2232                     if( pObj )
2233                     {
2234 						// Check if member list has changed
2235 						bool bObjChanged = false;
2236 						if( pItem->mpObject != NULL && pItem->maMemberList.mpMemberNames != NULL )
2237 						{
2238 							SbxArray* pProps = pObj->GetProperties();
2239 							sal_uInt16 nPropCount = pProps->Count();
2240 							for( sal_uInt16 i = 0 ; i < nPropCount - 3 ; i++ )
2241 							{
2242 								SbxVariable* pVar_ = pProps->Get( i );
2243 								String aName( pVar_->GetName() );
2244 								if( pItem->maMemberList.mpMemberNames[i] != aName )
2245 								{
2246 									bObjChanged = true;
2247 									break;
2248 								}
2249 							}
2250 							if( bObjChanged )
2251 								bCollapse = true;
2252 						}
2253 
2254 						pItem->mpObject = pObj;
2255 						implEnableChildren( pEntry, true );
2256 						aTypeStr = getBasicObjectTypeName( pObj );
2257 					}
2258 					else
2259 					{
2260 						aWatchStr = String( RTL_CONSTASCII_USTRINGPARAM( "Null" ) );
2261 						if( pItem->mpObject != NULL )
2262 						{
2263 							bCollapse = true;
2264 							pItem->clearWatchItem( false );
2265 
2266 							implEnableChildren( pEntry, false );
2267 						}
2268 					}
2269 				}
2270 				else
2271 				{
2272 					if( pItem->mpObject != NULL )
2273 					{
2274 						bCollapse = true;
2275 						pItem->clearWatchItem( false );
2276 
2277 						implEnableChildren( pEntry, false );
2278 					}
2279 
2280 					bool bString = ((sal_uInt8)eType == (sal_uInt8)SbxSTRING);
2281 					String aStrStr( RTL_CONSTASCII_USTRINGPARAM( "\"" ) );
2282 					if( bString )
2283 						aWatchStr += aStrStr;
2284 					aWatchStr += pVar->GetString();
2285 					if( bString )
2286 						aWatchStr += aStrStr;
2287 				}
2288 				if( !aTypeStr.Len() )
2289 				{
2290 					if( !pVar->IsFixed() )
2291 						aTypeStr = String( RTL_CONSTASCII_USTRINGPARAM( "Variant/" ) );
2292 					aTypeStr += getBasicTypeName( pVar->GetType() );
2293 				}
2294 			}
2295 			else if( !bArrayElement )
2296 				aWatchStr += String( RTL_CONSTASCII_USTRINGPARAM( "<Out of Scope>" ) );
2297 
2298 			if( bCollapse )
2299 				implCollapseModifiedObjectEntry( pEntry, this );
2300 
2301 		}
2302 		else if( bBasicStopped )
2303 		{
2304             if( pItem->mpObject || pItem->mpArray )
2305 			{
2306 				implCollapseModifiedObjectEntry( pEntry, this );
2307 				pItem->mpObject = NULL;
2308 			}
2309 		}
2310 
2311 		SvHeaderTabListBox::SetEntryText( aWatchStr, pEntry, ITEM_ID_VALUE-1 );
2312 		SvHeaderTabListBox::SetEntryText( aTypeStr, pEntry, ITEM_ID_TYPE-1 );
2313 
2314 		pEntry = Next( pEntry );
2315 	}
2316 
2317 	// Force redraw
2318     Invalidate();
2319 
2320 	SbxBase::ResetError();
2321 	if( eOld != SbxERR_OK )
2322 		SbxBase::SetError( eOld );
2323 	setBasicWatchMode( false );
2324 }
2325 
2326