xref: /trunk/main/basctl/source/basicide/baside2b.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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