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