1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_starmath.hxx" 30 31 32 #include <com/sun/star/accessibility/XAccessible.hpp> 33 #include <com/sun/star/accessibility/AccessibleEventObject.hpp> 34 #include <com/sun/star/accessibility/AccessibleEventId.hpp> 35 #include <com/sun/star/accessibility/AccessibleStateType.hpp> 36 #include <toolkit/helper/vclunohelper.hxx> 37 38 39 #include "starmath.hrc" 40 #define ITEMID_FONT 1 41 #define ITEMID_FONTHEIGHT 2 42 #define ITEMID_LRSPACE 3 43 #define ITEMID_WEIGHT 4 44 45 46 #include <vcl/menu.hxx> 47 #include <editeng/editview.hxx> 48 #include <editeng/editeng.hxx> 49 #include <editeng/editstat.hxx> 50 #include <editeng/eeitem.hxx> 51 #include <sfx2/dispatch.hxx> 52 #include <svl/intitem.hxx> 53 #include <svl/itempool.hxx> 54 #include <svl/stritem.hxx> 55 #include <editeng/fhgtitem.hxx> 56 #include <editeng/wghtitem.hxx> 57 #include <editeng/lrspitem.hxx> 58 #include <svl/itemset.hxx> 59 #include <editeng/fontitem.hxx> 60 #include <sfx2/viewfrm.hxx> 61 62 #include "edit.hxx" 63 #include "view.hxx" 64 #include "document.hxx" 65 #include "config.hxx" 66 67 #define SCROLL_LINE 24 68 69 #define MINWIDTH 200 70 #define MINHEIGHT 200 71 #define MINSPLIT 40 72 #define SPLITTERWIDTH 2 73 74 75 using namespace com::sun::star::accessibility; 76 using namespace com::sun::star; 77 using namespace com::sun::star::uno; 78 79 //////////////////////////////////////// 80 81 82 void SmGetLeftSelectionPart(const ESelection aSel, 83 sal_uInt16 &nPara, sal_uInt16 &nPos) 84 // returns paragraph number and position of the selections left part 85 { 86 // compare start and end of selection and use the one that comes first 87 if ( aSel.nStartPara < aSel.nEndPara 88 || (aSel.nStartPara == aSel.nEndPara && aSel.nStartPos < aSel.nEndPos) ) 89 { nPara = aSel.nStartPara; 90 nPos = aSel.nStartPos; 91 } 92 else 93 { nPara = aSel.nEndPara; 94 nPos = aSel.nEndPos; 95 } 96 } 97 98 //////////////////////////////////////// 99 100 SmEditWindow::SmEditWindow( SmCmdBoxWindow &rMyCmdBoxWin ) : 101 Window (&rMyCmdBoxWin), 102 DropTargetHelper ( this ), 103 pAccessible (0), 104 rCmdBox (rMyCmdBoxWin), 105 pEditView (0), 106 pHScrollBar (0), 107 pVScrollBar (0), 108 pScrollBox (0) 109 { 110 SetHelpId(HID_SMA_COMMAND_WIN_EDIT); 111 SetMapMode(MAP_PIXEL); 112 113 // Even RTL languages don't use RTL for math 114 rCmdBox.GetEditWindow()->EnableRTL( sal_False ); 115 116 ApplyColorConfigValues( SM_MOD()->GetColorConfig() ); 117 118 // compare DataChanged 119 SetBackground( GetSettings().GetStyleSettings().GetWindowColor() ); 120 121 aModifyTimer.SetTimeoutHdl(LINK(this, SmEditWindow, ModifyTimerHdl)); 122 aModifyTimer.SetTimeout(500); 123 124 aCursorMoveTimer.SetTimeoutHdl(LINK(this, SmEditWindow, CursorMoveTimerHdl)); 125 aCursorMoveTimer.SetTimeout(500); 126 127 // if not called explicitly the this edit window within the 128 // command window will just show an empty gray panel. 129 Show(); 130 } 131 132 133 SmEditWindow::~SmEditWindow() 134 { 135 aCursorMoveTimer.Stop(); 136 aModifyTimer.Stop(); 137 138 139 // #112565# clean up of classes used for accessibility 140 // must be done before EditView (and thus EditEngine) is no longer 141 // available for those classes. 142 if (pAccessible) 143 pAccessible->ClearWin(); // make Accessible defunctional 144 // Note: memory for pAccessible will be freed when the reference 145 // xAccessible is released. 146 147 if (pEditView) 148 { 149 EditEngine *pEditEngine = pEditView->GetEditEngine(); 150 if (pEditEngine) 151 { 152 pEditEngine->SetStatusEventHdl( Link() ); 153 pEditEngine->RemoveView( pEditView ); 154 } 155 } 156 delete pEditView; 157 delete pHScrollBar; 158 delete pVScrollBar; 159 delete pScrollBox; 160 } 161 162 void SmEditWindow::InvalidateSlots() 163 { 164 SfxBindings& rBind = GetView()->GetViewFrame()->GetBindings(); 165 rBind.Invalidate(SID_COPY); 166 rBind.Invalidate(SID_CUT); 167 rBind.Invalidate(SID_DELETE); 168 } 169 170 SmViewShell * SmEditWindow::GetView() 171 { 172 return rCmdBox.GetView(); 173 } 174 175 176 SmDocShell * SmEditWindow::GetDoc() 177 { 178 SmViewShell *pView = rCmdBox.GetView(); 179 return pView ? pView->GetDoc() : 0; 180 } 181 182 183 EditEngine * SmEditWindow::GetEditEngine() 184 { 185 EditEngine *pEditEng = 0; 186 if (pEditView) 187 pEditEng = pEditView->GetEditEngine(); 188 else 189 { 190 SmDocShell *pDoc = GetDoc(); 191 if (pDoc) 192 pEditEng = &pDoc->GetEditEngine(); 193 } 194 return pEditEng; 195 } 196 197 198 SfxItemPool * SmEditWindow::GetEditEngineItemPool() 199 { 200 SmDocShell *pDoc = GetDoc(); 201 return pDoc ? &pDoc->GetEditEngineItemPool() : 0; 202 } 203 204 void SmEditWindow::ApplyColorConfigValues( const svtools::ColorConfig &rColorCfg ) 205 { 206 // Note: SetBackground still done in SmEditWindow::DataChanged 207 #if OSL_DEBUG_LEVEL > 1 208 // ColorData nVal = rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor; 209 #endif 210 SetTextColor( rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor ); 211 Invalidate(); 212 } 213 214 void SmEditWindow::DataChanged( const DataChangedEvent& ) 215 { 216 const StyleSettings aSettings( GetSettings().GetStyleSettings() ); 217 218 ApplyColorConfigValues( SM_MOD()->GetColorConfig() ); 219 SetBackground( aSettings.GetWindowColor() ); 220 221 // edit fields in other Applications use this font instead of 222 // the application font thus we use this one too 223 SetPointFont( aSettings.GetFieldFont() /*aSettings.GetAppFont()*/ ); 224 225 EditEngine *pEditEngine = GetEditEngine(); 226 SfxItemPool *pEditEngineItemPool = GetEditEngineItemPool(); 227 228 if (pEditEngine && pEditEngineItemPool) 229 { 230 //! 231 //! see also SmDocShell::GetEditEngine() ! 232 //! 233 234 pEditEngine->SetDefTab( sal_uInt16( GetTextWidth( C2S("XXXX") ) ) ); 235 236 SetEditEngineDefaultFonts( *pEditEngine, *pEditEngineItemPool ); 237 238 // forces new settings to be used 239 // unfortunately this resets the whole edit engine 240 // thus we need to save at least the text 241 String aTxt( pEditEngine->GetText( LINEEND_LF ) ); 242 pEditEngine->Clear(); //#77957 incorrect font size 243 pEditEngine->SetText( aTxt ); 244 } 245 246 AdjustScrollBars(); 247 Resize(); 248 } 249 250 IMPL_LINK( SmEditWindow, ModifyTimerHdl, Timer *, EMPTYARG /*pTimer*/ ) 251 { 252 SmModule *pp = SM_MOD(); 253 if (pp->GetConfig()->IsAutoRedraw()) 254 Flush(); 255 aModifyTimer.Stop(); 256 return 0; 257 } 258 259 260 IMPL_LINK(SmEditWindow, CursorMoveTimerHdl, Timer *, EMPTYARG /*pTimer*/) 261 // every once in a while check cursor position (selection) of edit 262 // window and if it has changed (try to) set the formula-cursor 263 // according to that. 264 { 265 ESelection aNewSelection (GetSelection()); 266 267 if (!aNewSelection.IsEqual(aOldSelection)) 268 { SmViewShell *pView = rCmdBox.GetView(); 269 270 if (pView) 271 { 272 // get row and column to look for 273 sal_uInt16 nRow, nCol; 274 SmGetLeftSelectionPart(aNewSelection, nRow, nCol); 275 nRow++; 276 nCol++; 277 278 pView->GetGraphicWindow().SetCursorPos(nRow, nCol); 279 280 aOldSelection = aNewSelection; 281 } 282 } 283 aCursorMoveTimer.Stop(); 284 285 return 0; 286 } 287 288 289 void SmEditWindow::Resize() 290 { 291 if (!pEditView) 292 CreateEditView(); 293 294 if (pEditView) 295 { 296 pEditView->SetOutputArea(AdjustScrollBars()); 297 pEditView->ShowCursor(); 298 299 DBG_ASSERT( pEditView->GetEditEngine(), "EditEngine missing" ); 300 const long nMaxVisAreaStart = pEditView->GetEditEngine()->GetTextHeight() - 301 pEditView->GetOutputArea().GetHeight(); 302 if (pEditView->GetVisArea().Top() > nMaxVisAreaStart) 303 { 304 Rectangle aVisArea(pEditView->GetVisArea() ); 305 aVisArea.Top() = (nMaxVisAreaStart > 0 ) ? nMaxVisAreaStart : 0; 306 aVisArea.SetSize(pEditView->GetOutputArea().GetSize()); 307 pEditView->SetVisArea(aVisArea); 308 pEditView->ShowCursor(); 309 } 310 InitScrollBars(); 311 } 312 Invalidate(); 313 } 314 315 void SmEditWindow::MouseButtonUp(const MouseEvent &rEvt) 316 { 317 if (pEditView) 318 pEditView->MouseButtonUp(rEvt); 319 else 320 Window::MouseButtonUp (rEvt); 321 322 // ggf FormulaCursor neu positionieren 323 CursorMoveTimerHdl(&aCursorMoveTimer); 324 InvalidateSlots(); 325 } 326 327 void SmEditWindow::MouseButtonDown(const MouseEvent &rEvt) 328 { 329 if (pEditView) 330 pEditView->MouseButtonDown(rEvt); 331 else 332 Window::MouseButtonDown (rEvt); 333 334 GrabFocus(); 335 } 336 337 void SmEditWindow::Command(const CommandEvent& rCEvt) 338 { 339 sal_Bool bForwardEvt = sal_True; 340 if (rCEvt.GetCommand() == COMMAND_CONTEXTMENU) 341 { 342 GetParent()->ToTop(); 343 344 Point aPoint = rCEvt.GetMousePosPixel(); 345 PopupMenu* pPopupMenu = new PopupMenu(SmResId(RID_COMMANDMENU)); 346 347 // added for replaceability of context menus #96085, #93782 348 Menu* pMenu = NULL; 349 ::com::sun::star::ui::ContextMenuExecuteEvent aEvent; 350 aEvent.SourceWindow = VCLUnoHelper::GetInterface( this ); 351 aEvent.ExecutePosition.X = aPoint.X(); 352 aEvent.ExecutePosition.Y = aPoint.Y(); 353 ::rtl::OUString sDummy; 354 if ( GetView()->TryContextMenuInterception( *pPopupMenu, sDummy, pMenu, aEvent ) ) 355 { 356 if ( pMenu ) 357 { 358 delete pPopupMenu; 359 pPopupMenu = (PopupMenu*) pMenu; 360 } 361 } 362 363 pPopupMenu->SetSelectHdl(LINK(this, SmEditWindow, MenuSelectHdl)); 364 365 pPopupMenu->Execute( this, aPoint ); 366 delete pPopupMenu; 367 bForwardEvt = sal_False; 368 } 369 else if (rCEvt.GetCommand() == COMMAND_WHEEL) 370 bForwardEvt = !HandleWheelCommands( rCEvt ); 371 372 if (bForwardEvt) 373 { 374 if (pEditView) 375 pEditView->Command( rCEvt ); 376 else 377 Window::Command (rCEvt); 378 } 379 } 380 381 382 sal_Bool SmEditWindow::HandleWheelCommands( const CommandEvent &rCEvt ) 383 { 384 sal_Bool bCommandHandled = sal_False; // true if the CommandEvent needs not 385 // to be passed on (because it has fully 386 // been taken care of). 387 388 const CommandWheelData* pWData = rCEvt.GetWheelData(); 389 if (pWData) 390 { 391 if (COMMAND_WHEEL_ZOOM == pWData->GetMode()) 392 bCommandHandled = sal_True; // no zooming in Command window 393 else 394 bCommandHandled = HandleScrollCommand( rCEvt, pHScrollBar, pVScrollBar); 395 } 396 397 return bCommandHandled; 398 } 399 400 401 IMPL_LINK_INLINE_START( SmEditWindow, MenuSelectHdl, Menu *, pMenu ) 402 { 403 SmViewShell *pViewSh = rCmdBox.GetView(); 404 if (pViewSh) 405 pViewSh->GetViewFrame()->GetDispatcher()->Execute( 406 SID_INSERTCOMMAND, SFX_CALLMODE_STANDARD, 407 new SfxInt16Item(SID_INSERTCOMMAND, pMenu->GetCurItemId()), 0L); 408 return 0; 409 } 410 IMPL_LINK_INLINE_END( SmEditWindow, MenuSelectHdl, Menu *, pMenu ) 411 412 void SmEditWindow::KeyInput(const KeyEvent& rKEvt) 413 { 414 if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE) 415 { 416 sal_Bool bCallBase = sal_True; 417 SfxViewShell* pViewShell = GetView(); 418 if ( pViewShell && pViewShell->ISA(SmViewShell) ) 419 { 420 // Terminate possible InPlace mode 421 bCallBase = !pViewShell->Escape(); 422 } 423 if ( bCallBase ) 424 Window::KeyInput( rKEvt ); 425 } 426 else 427 { 428 // Timer neu starten, um den Handler (auch bei laengeren Eingaben) 429 // moeglichst nur einmal am Ende aufzurufen. 430 aCursorMoveTimer.Start(); 431 432 DBG_ASSERT( pEditView, "EditView missing (NULL pointer)" ); 433 if (!pEditView) 434 CreateEditView(); 435 if ( !pEditView->PostKeyEvent(rKEvt) ) 436 { 437 SmViewShell *pView = GetView(); 438 if ( pView && !pView->KeyInput(rKEvt) ) 439 { 440 /* fuert bei F1 (Hilfe) zum Zerstoeren von this! */ 441 Flush(); 442 if ( aModifyTimer.IsActive() ) 443 aModifyTimer.Stop(); 444 Window::KeyInput(rKEvt); 445 } 446 else 447 { 448 //SFX hat evtl. Slot an der View gecallt und dabei (wg. Hack 449 //im SFX) den Focus auf die View gesetzt 450 SfxViewShell* pVShell = GetView(); 451 if ( pVShell && pVShell->ISA(SmViewShell) && 452 ((SmViewShell*)pVShell)->GetGraphicWindow().HasFocus() ) 453 { 454 GrabFocus(); 455 } 456 } 457 } 458 else 459 { 460 // have doc-shell modified only for formula input/change and not 461 // cursor travelling and such things... 462 SmDocShell *pDocShell = GetDoc(); 463 if (pDocShell) 464 pDocShell->SetModified( GetEditEngine()->IsModified() ); 465 466 aModifyTimer.Start(); 467 } 468 469 InvalidateSlots(); 470 } 471 } 472 473 void SmEditWindow::Paint(const Rectangle& rRect) 474 { 475 if (!pEditView) 476 CreateEditView(); 477 pEditView->Paint(rRect); 478 } 479 480 void SmEditWindow::CreateEditView() 481 { 482 EditEngine *pEditEngine = GetEditEngine(); 483 484 //! pEditEngine and pEditView may be 0. 485 //! For example when the program is used by the document-converter 486 if (!pEditView && pEditEngine) 487 { 488 pEditView = new EditView( pEditEngine, this ); 489 pEditEngine->InsertView( pEditView ); 490 491 if (!pVScrollBar) 492 pVScrollBar = new ScrollBar(this, WinBits(WB_VSCROLL)); 493 if (!pHScrollBar) 494 pHScrollBar = new ScrollBar(this, WinBits(WB_HSCROLL)); 495 if (!pScrollBox) 496 pScrollBox = new ScrollBarBox(this); 497 pVScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl)); 498 pHScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl)); 499 pVScrollBar->EnableDrag( sal_True ); 500 pHScrollBar->EnableDrag( sal_True ); 501 502 pEditView->SetOutputArea(AdjustScrollBars()); 503 504 ESelection eSelection; 505 506 pEditView->SetSelection(eSelection); 507 Update(); 508 pEditView->ShowCursor(sal_True, sal_True); 509 510 pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) ); 511 SetPointer(pEditView->GetPointer()); 512 513 SetScrollBarRanges(); 514 } 515 } 516 517 518 IMPL_LINK( SmEditWindow, EditStatusHdl, EditStatus *, EMPTYARG /*pStat*/ ) 519 { 520 if (!pEditView) 521 return 1; 522 else 523 { 524 Resize(); 525 return 0; 526 } 527 } 528 529 IMPL_LINK_INLINE_START( SmEditWindow, ScrollHdl, ScrollBar *, EMPTYARG /*pScrollBar*/ ) 530 { 531 DBG_ASSERT(pEditView, "EditView missing"); 532 if (pEditView) 533 { 534 pEditView->SetVisArea(Rectangle(Point(pHScrollBar->GetThumbPos(), 535 pVScrollBar->GetThumbPos()), 536 pEditView->GetVisArea().GetSize())); 537 pEditView->Invalidate(); 538 } 539 return 0; 540 } 541 IMPL_LINK_INLINE_END( SmEditWindow, ScrollHdl, ScrollBar *, pScrollBar ) 542 543 Rectangle SmEditWindow::AdjustScrollBars() 544 { 545 const Size aOut( GetOutputSizePixel() ); 546 Point aPoint; 547 Rectangle aRect( aPoint, aOut ); 548 549 if (pVScrollBar && pHScrollBar && pScrollBox) 550 { 551 const long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize(); 552 Point aPt( aRect.TopRight() ); aPt.X() -= nTmp -1L; 553 pVScrollBar->SetPosSizePixel( aPt, Size(nTmp, aOut.Height() - nTmp)); 554 555 aPt = aRect.BottomLeft(); aPt.Y() -= nTmp - 1L; 556 pHScrollBar->SetPosSizePixel( aPt, Size(aOut.Width() - nTmp, nTmp)); 557 558 aPt.X() = pHScrollBar->GetSizePixel().Width(); 559 aPt.Y() = pVScrollBar->GetSizePixel().Height(); 560 pScrollBox->SetPosSizePixel(aPt, Size(nTmp, nTmp )); 561 562 aRect.Right() = aPt.X() - 2; 563 aRect.Bottom() = aPt.Y() - 2; 564 } 565 return aRect; 566 } 567 568 void SmEditWindow::SetScrollBarRanges() 569 { 570 // Extra-Methode, nicht InitScrollBars, da auch fuer EditEngine-Events. 571 EditEngine *pEditEngine = GetEditEngine(); 572 if (pVScrollBar && pHScrollBar && pEditEngine && pEditView) 573 { 574 long nTmp = pEditEngine->GetTextHeight(); 575 pVScrollBar->SetRange(Range(0, nTmp)); 576 pVScrollBar->SetThumbPos(pEditView->GetVisArea().Top()); 577 578 nTmp = pEditEngine->GetPaperSize().Width(); 579 pHScrollBar->SetRange(Range(0,nTmp)); 580 pHScrollBar->SetThumbPos(pEditView->GetVisArea().Left()); 581 } 582 } 583 584 void SmEditWindow::InitScrollBars() 585 { 586 if (pVScrollBar && pHScrollBar && pScrollBox && pEditView) 587 { 588 const Size aOut( pEditView->GetOutputArea().GetSize() ); 589 pVScrollBar->SetVisibleSize(aOut.Height()); 590 pVScrollBar->SetPageSize(aOut.Height() * 8 / 10); 591 pVScrollBar->SetLineSize(aOut.Height() * 2 / 10); 592 593 pHScrollBar->SetVisibleSize(aOut.Width()); 594 pHScrollBar->SetPageSize(aOut.Width() * 8 / 10); 595 pHScrollBar->SetLineSize(SCROLL_LINE ); 596 597 SetScrollBarRanges(); 598 599 pVScrollBar->Show(); 600 pHScrollBar->Show(); 601 pScrollBox->Show(); 602 } 603 } 604 605 606 String SmEditWindow::GetText() const 607 { 608 String aText; 609 EditEngine *pEditEngine = const_cast< SmEditWindow* >(this)->GetEditEngine(); 610 DBG_ASSERT( pEditEngine, "EditEngine missing" ); 611 if (pEditEngine) 612 aText = pEditEngine->GetText( LINEEND_LF ); 613 return aText; 614 } 615 616 617 void SmEditWindow::SetText(const XubString& rText) 618 { 619 EditEngine *pEditEngine = GetEditEngine(); 620 DBG_ASSERT( pEditEngine, "EditEngine missing" ); 621 if (pEditEngine && !pEditEngine->IsModified()) 622 { 623 if (!pEditView) 624 CreateEditView(); 625 626 ESelection eSelection = pEditView->GetSelection(); 627 628 pEditEngine->SetText(rText); 629 pEditEngine->ClearModifyFlag(); 630 631 //! Hier die Timer neu zu starten verhindert, dass die Handler fuer andere 632 //! (im Augenblick nicht mehr aktive) Math Tasks aufgerufen werden. 633 aModifyTimer.Start(); 634 aCursorMoveTimer.Start(); 635 636 pEditView->SetSelection(eSelection); 637 } 638 } 639 640 641 void SmEditWindow::GetFocus() 642 { 643 Window::GetFocus(); 644 645 if (xAccessible.is()) 646 { 647 // Note: will implicitly send the AccessibleStateType::FOCUSED event 648 ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper(); 649 if (pHelper) 650 pHelper->SetFocus( sal_True ); 651 } 652 653 if (!pEditView) 654 CreateEditView(); 655 EditEngine *pEditEngine = GetEditEngine(); 656 if (pEditEngine) 657 pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) ); 658 } 659 660 661 void SmEditWindow::LoseFocus() 662 { 663 EditEngine *pEditEngine = GetEditEngine(); 664 if (pEditEngine) 665 pEditEngine->SetStatusEventHdl( Link() ); 666 667 Window::LoseFocus(); 668 669 if (xAccessible.is()) 670 { 671 // Note: will implicitly send the AccessibleStateType::FOCUSED event 672 ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper(); 673 if (pHelper) 674 pHelper->SetFocus( sal_False ); 675 } 676 } 677 678 679 sal_Bool SmEditWindow::IsAllSelected() const 680 { 681 sal_Bool bRes = sal_False; 682 EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine(); 683 DBG_ASSERT( pEditView, "NULL pointer" ); 684 DBG_ASSERT( pEditEngine, "NULL pointer" ); 685 if (pEditEngine && pEditView) 686 { 687 ESelection eSelection( pEditView->GetSelection() ); 688 sal_Int32 nParaCnt = pEditEngine->GetParagraphCount(); 689 if (!(nParaCnt - 1)) 690 { 691 String Text( pEditEngine->GetText( LINEEND_LF ) ); 692 bRes = !eSelection.nStartPos && (eSelection.nEndPos == Text.Len () - 1); 693 } 694 else 695 { 696 bRes = !eSelection.nStartPara && (eSelection.nEndPara == nParaCnt - 1); 697 } 698 } 699 return bRes; 700 } 701 702 void SmEditWindow::SelectAll() 703 { 704 DBG_ASSERT( pEditView, "NULL pointer" ); 705 if (pEditView) 706 { 707 // 0xFFFF as last two parameters refers to the end of the text 708 pEditView->SetSelection( ESelection( 0, 0, 0xFFFF, 0xFFFF ) ); 709 } 710 } 711 712 void SmEditWindow::InsertCommand(sal_uInt16 nCommand) 713 { 714 DBG_ASSERT( pEditView, "EditView missing" ); 715 if (pEditView) 716 { 717 //Anfang der Selektion merken und hinterher den Cursor daraufsetzen. Nur so 718 //macht das SelNextMark() Sinn. 719 ESelection aSelection = pEditView->GetSelection(); 720 aSelection.nEndPos = aSelection.nStartPos; 721 aSelection.nEndPara = aSelection.nStartPara; 722 723 DBG_ASSERT( pEditView, "NULL pointer" ); 724 String aText = String(SmResId(nCommand)); 725 pEditView->InsertText(aText); 726 727 if (HasMark(aText)) 728 { // set selection to next mark 729 pEditView->SetSelection(aSelection); 730 SelNextMark(); 731 } 732 else 733 { // set selection after inserted text 734 aSelection.nEndPos = aSelection.nEndPos + sal::static_int_cast< xub_StrLen >(aText.Len()); 735 aSelection.nStartPos = aSelection.nEndPos; 736 pEditView->SetSelection(aSelection); 737 } 738 739 aModifyTimer.Start(); 740 aCursorMoveTimer.Start(); 741 742 GrabFocus(); 743 } 744 } 745 746 void SmEditWindow::MarkError(const Point &rPos) 747 { 748 DBG_ASSERT( pEditView, "EditView missing" ); 749 if (pEditView) 750 { 751 const xub_StrLen nCol = sal::static_int_cast< xub_StrLen >(rPos.X()); 752 const sal_uInt16 nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1); 753 754 pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol)); 755 GrabFocus(); 756 } 757 } 758 759 void SmEditWindow::SelNextMark() 760 { 761 EditEngine *pEditEngine = GetEditEngine(); 762 DBG_ASSERT( pEditView, "NULL pointer" ); 763 DBG_ASSERT( pEditEngine, "NULL pointer" ); 764 if (pEditEngine && pEditView) 765 { 766 ESelection eSelection = pEditView->GetSelection(); 767 sal_uInt16 Pos = eSelection.nEndPos; 768 String aMark (C2S("<?>")); 769 String aText; 770 sal_uInt16 nCounts = pEditEngine->GetParagraphCount(); 771 772 while (eSelection.nEndPara < nCounts) 773 { 774 aText = pEditEngine->GetText( eSelection.nEndPara ); 775 Pos = aText.Search(aMark, Pos); 776 777 if (Pos != STRING_NOTFOUND) 778 { 779 pEditView->SetSelection(ESelection (eSelection.nEndPara, Pos, eSelection.nEndPara, Pos + 3)); 780 break; 781 } 782 783 Pos = 0; 784 eSelection.nEndPara++; 785 } 786 } 787 } 788 789 void SmEditWindow::SelPrevMark() 790 { 791 EditEngine *pEditEngine = GetEditEngine(); 792 DBG_ASSERT( pEditEngine, "NULL pointer" ); 793 DBG_ASSERT( pEditView, "NULL pointer" ); 794 if (pEditEngine && pEditView) 795 { 796 ESelection eSelection = pEditView->GetSelection(); 797 sal_uInt16 Pos = STRING_NOTFOUND; 798 xub_StrLen Max = eSelection.nStartPos; 799 String Text( pEditEngine->GetText( eSelection.nStartPara ) ); 800 String aMark (C2S("<?>")); 801 sal_uInt16 nCounts = pEditEngine->GetParagraphCount(); 802 803 do 804 { 805 sal_uInt16 Fnd = Text.Search(aMark, 0); 806 807 while ((Fnd < Max) && (Fnd != STRING_NOTFOUND)) 808 { 809 Pos = Fnd; 810 Fnd = Text.Search(aMark, Fnd + 1); 811 } 812 813 if (Pos == STRING_NOTFOUND) 814 { 815 eSelection.nStartPara--; 816 Text = pEditEngine->GetText( eSelection.nStartPara ); 817 Max = Text.Len(); 818 } 819 } 820 while ((eSelection.nStartPara < nCounts) && 821 (Pos == STRING_NOTFOUND)); 822 823 if (Pos != STRING_NOTFOUND) 824 { 825 pEditView->SetSelection(ESelection (eSelection.nStartPara, Pos, eSelection.nStartPara, Pos + 3)); 826 } 827 } 828 } 829 830 sal_Bool SmEditWindow::HasMark(const String& rText) const 831 // returns true iff 'rText' contains a mark 832 { 833 return rText.SearchAscii("<?>", 0) != STRING_NOTFOUND; 834 } 835 836 void SmEditWindow::MouseMove(const MouseEvent &rEvt) 837 { 838 if (pEditView) 839 pEditView->MouseMove(rEvt); 840 } 841 842 sal_Int8 SmEditWindow::AcceptDrop( const AcceptDropEvent& /*rEvt*/ ) 843 { 844 return pEditView ? /*pEditView->QueryDrop( rEvt )*/DND_ACTION_NONE: DND_ACTION_NONE; 845 } 846 847 sal_Int8 SmEditWindow::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ ) 848 { 849 return pEditView ? /*pEditView->Drop( rEvt )*/DND_ACTION_NONE : DND_ACTION_NONE; 850 } 851 852 ESelection SmEditWindow::GetSelection() const 853 { 854 // pointer may be 0 when reloading a document and the old view 855 // was already destroyed 856 //(DBG_ASSERT( pEditView, "NULL pointer" ); 857 ESelection eSel; 858 if (pEditView) 859 eSel = pEditView->GetSelection(); 860 return eSel; 861 } 862 863 void SmEditWindow::SetSelection(const ESelection &rSel) 864 { 865 DBG_ASSERT( pEditView, "NULL pointer" ); 866 if (pEditView) 867 pEditView->SetSelection(rSel); 868 InvalidateSlots(); 869 } 870 871 sal_Bool SmEditWindow::IsEmpty() const 872 { 873 EditEngine *pEditEngine = ((SmEditWindow *) this)->GetEditEngine(); 874 sal_Bool bEmpty = sal::static_int_cast< sal_Bool >( 875 pEditEngine ? pEditEngine->GetTextLen() == 0 : sal_False); 876 return bEmpty; 877 } 878 879 sal_Bool SmEditWindow::IsSelected() const 880 { 881 return pEditView ? pEditView->HasSelection() : sal_False; 882 } 883 884 void SmEditWindow::Cut() 885 { 886 DBG_ASSERT( pEditView, "EditView missing" ); 887 if (pEditView) 888 { 889 pEditView->Cut(); 890 GetDoc()->SetModified( sal_True ); 891 } 892 } 893 894 void SmEditWindow::Copy() 895 { 896 DBG_ASSERT( pEditView, "EditView missing" ); 897 if (pEditView) 898 pEditView->Copy(); 899 } 900 901 void SmEditWindow::Paste() 902 { 903 DBG_ASSERT( pEditView, "EditView missing" ); 904 if (pEditView) 905 { 906 pEditView->Paste(); 907 GetDoc()->SetModified( sal_True ); 908 } 909 } 910 911 void SmEditWindow::Delete() 912 { 913 DBG_ASSERT( pEditView, "EditView missing" ); 914 if (pEditView) 915 { 916 pEditView->DeleteSelected(); 917 GetDoc()->SetModified( sal_True ); 918 } 919 } 920 921 void SmEditWindow::InsertText(const String& Text) 922 { 923 DBG_ASSERT( pEditView, "EditView missing" ); 924 if (pEditView) 925 { 926 pEditView->InsertText(Text); 927 aModifyTimer.Start(); 928 aCursorMoveTimer.Start(); 929 } 930 } 931 932 void SmEditWindow::Flush() 933 { 934 EditEngine *pEditEngine = GetEditEngine(); 935 if (pEditEngine && pEditEngine->IsModified()) 936 { 937 pEditEngine->ClearModifyFlag(); 938 SmViewShell *pViewSh = rCmdBox.GetView(); 939 if (pViewSh) 940 { 941 pViewSh->GetViewFrame()->GetDispatcher()->Execute( 942 SID_TEXT, SFX_CALLMODE_STANDARD, 943 new SfxStringItem(SID_TEXT, GetText()), 0L); 944 } 945 } 946 947 if (aCursorMoveTimer.IsActive()) 948 { 949 aCursorMoveTimer.Stop(); 950 // ggf noch die (neue) FormulaCursor Position setzen 951 CursorMoveTimerHdl(&aCursorMoveTimer); 952 } 953 } 954 955 956 void SmEditWindow::DeleteEditView( SmViewShell & /*rView*/ ) 957 { 958 if (pEditView) 959 { 960 EditEngine *pEditEngine = pEditView->GetEditEngine(); 961 if (pEditEngine) 962 { 963 pEditEngine->SetStatusEventHdl( Link() ); 964 pEditEngine->RemoveView( pEditView ); 965 } 966 delete pEditView; 967 pEditView = 0; 968 } 969 } 970 971 972 uno::Reference< XAccessible > SmEditWindow::CreateAccessible() 973 { 974 if (!pAccessible) 975 { 976 pAccessible = new SmEditAccessible( this ); 977 xAccessible = pAccessible; 978 pAccessible->Init(); 979 } 980 return xAccessible; 981 } 982 983