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