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