nss: upgrade to release 3.73
[LibreOffice.git] / starmath / source / edit.cxx
blob152c269b1cc4d2ff0aa5ab087b3a2722d5f30fde
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <starmath.hrc>
21 #include <helpids.h>
23 #include <vcl/commandevent.hxx>
24 #include <vcl/event.hxx>
25 #include <vcl/scrbar.hxx>
26 #include <vcl/settings.hxx>
28 #include <editeng/editview.hxx>
29 #include <editeng/editeng.hxx>
30 #include <sfx2/dispatch.hxx>
31 #include <sfx2/sfxsids.hrc>
32 #include <svl/stritem.hxx>
33 #include <sfx2/viewfrm.hxx>
34 #include <svx/AccessibleTextHelper.hxx>
35 #include <svtools/colorcfg.hxx>
36 #include <osl/diagnose.h>
38 #include <edit.hxx>
39 #include <smmod.hxx>
40 #include <view.hxx>
41 #include <document.hxx>
42 #include "cfgitem.hxx"
43 #include "accessibility.hxx"
44 #include <memory>
46 #define SCROLL_LINE 24
49 using namespace com::sun::star::accessibility;
50 using namespace com::sun::star;
53 void SmGetLeftSelectionPart(const ESelection &rSel,
54 sal_Int32 &nPara, sal_uInt16 &nPos)
55 // returns paragraph number and position of the selections left part
57 // compare start and end of selection and use the one that comes first
58 if ( rSel.nStartPara < rSel.nEndPara
59 || (rSel.nStartPara == rSel.nEndPara && rSel.nStartPos < rSel.nEndPos) )
60 { nPara = rSel.nStartPara;
61 nPos = rSel.nStartPos;
63 else
64 { nPara = rSel.nEndPara;
65 nPos = rSel.nEndPos;
69 bool SmEditWindow::IsInlineEditEnabled()
71 return SmViewShell::IsInlineEditEnabled();
75 SmEditWindow::SmEditWindow( SmCmdBoxWindow &rMyCmdBoxWin ) :
76 Window (&rMyCmdBoxWin, WB_BORDER),
77 DropTargetHelper ( this ),
78 rCmdBox (rMyCmdBoxWin),
79 aModifyIdle ("SmEditWindow ModifyIdle"),
80 aCursorMoveIdle ("SmEditWindow CursorMoveIdle")
82 set_id("math_edit");
83 SetHelpId(HID_SMA_COMMAND_WIN_EDIT);
84 SetMapMode(MapMode(MapUnit::MapPixel));
86 // Even RTL languages don't use RTL for math
87 EnableRTL( false );
89 // compare DataChanged
90 SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
92 aModifyIdle.SetInvokeHandler(LINK(this, SmEditWindow, ModifyTimerHdl));
93 aModifyIdle.SetPriority(TaskPriority::LOWEST);
95 if (!IsInlineEditEnabled())
97 aCursorMoveIdle.SetInvokeHandler(LINK(this, SmEditWindow, CursorMoveTimerHdl));
98 aCursorMoveIdle.SetPriority(TaskPriority::LOWEST);
101 // if not called explicitly the this edit window within the
102 // command window will just show an empty gray panel.
103 Show();
107 SmEditWindow::~SmEditWindow()
109 disposeOnce();
112 void SmEditWindow::dispose()
114 aModifyIdle.Stop();
116 StartCursorMove();
118 // clean up of classes used for accessibility
119 // must be done before EditView (and thus EditEngine) is no longer
120 // available for those classes.
121 if (mxAccessible.is())
123 mxAccessible->ClearWin(); // make Accessible nonfunctional
124 mxAccessible.clear();
127 if (pEditView)
129 EditEngine *pEditEngine = pEditView->GetEditEngine();
130 if (pEditEngine)
132 pEditEngine->SetStatusEventHdl( Link<EditStatus&,void>() );
133 pEditEngine->RemoveView( pEditView.get() );
135 pEditView.reset();
138 pHScrollBar.disposeAndClear();
139 pVScrollBar.disposeAndClear();
140 pScrollBox.disposeAndClear();
142 DropTargetHelper::dispose();
143 vcl::Window::dispose();
146 OUString SmEditWindow::GetSurroundingText() const
148 if (pEditView)
149 return pEditView->GetSurroundingText();
150 return OUString();
153 Selection SmEditWindow::GetSurroundingTextSelection() const
155 if (pEditView)
156 return pEditView->GetSurroundingTextSelection();
157 return Selection(0, 0);
160 bool SmEditWindow::DeleteSurroundingText(const Selection& rSelection)
162 if (pEditView)
163 return pEditView->DeleteSurroundingText(rSelection);
164 return false;
167 void SmEditWindow::StartCursorMove()
169 if (!IsInlineEditEnabled())
170 aCursorMoveIdle.Stop();
173 void SmEditWindow::InvalidateSlots()
175 SfxBindings& rBind = GetView()->GetViewFrame()->GetBindings();
176 rBind.Invalidate(SID_COPY);
177 rBind.Invalidate(SID_CUT);
178 rBind.Invalidate(SID_DELETE);
181 SmViewShell * SmEditWindow::GetView()
183 return rCmdBox.GetView();
187 SmDocShell * SmEditWindow::GetDoc()
189 SmViewShell *pView = rCmdBox.GetView();
190 return pView ? pView->GetDoc() : nullptr;
193 EditView * SmEditWindow::GetEditView()
195 return pEditView.get();
198 EditEngine * SmEditWindow::GetEditEngine()
200 EditEngine *pEditEng = nullptr;
201 if (pEditView)
202 pEditEng = pEditView->GetEditEngine();
203 else
205 SmDocShell *pDoc = GetDoc();
206 if (pDoc)
207 pEditEng = &pDoc->GetEditEngine();
209 return pEditEng;
212 void SmEditWindow::ApplySettings(vcl::RenderContext& rRenderContext)
214 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
215 rRenderContext.SetBackground(rStyleSettings.GetWindowColor());
218 void SmEditWindow::DataChanged( const DataChangedEvent& rDCEvt )
220 Window::DataChanged( rDCEvt );
222 if (!((rDCEvt.GetType() == DataChangedEventType::FONTS) ||
223 (rDCEvt.GetType() == DataChangedEventType::FONTSUBSTITUTION) ||
224 ((rDCEvt.GetType() == DataChangedEventType::SETTINGS) &&
225 (rDCEvt.GetFlags() & AllSettingsFlags::STYLE))))
226 return;
228 EditEngine *pEditEngine = GetEditEngine();
229 SmDocShell *pDoc = GetDoc();
231 if (pEditEngine && pDoc)
234 //! see also SmDocShell::GetEditEngine() !
236 const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
238 pDoc->UpdateEditEngineDefaultFonts(rStyleSettings.GetFieldTextColor());
239 pEditEngine->SetBackgroundColor(rStyleSettings.GetFieldColor());
240 pEditEngine->SetDefTab(sal_uInt16(GetTextWidth("XXXX")));
242 // forces new settings to be used
243 // unfortunately this resets the whole edit engine
244 // thus we need to save at least the text
245 OUString aTxt( pEditEngine->GetText() );
246 pEditEngine->Clear(); //incorrect font size
247 pEditEngine->SetText( aTxt );
249 AdjustScrollBars();
250 Resize();
253 Invalidate();
256 IMPL_LINK_NOARG( SmEditWindow, ModifyTimerHdl, Timer *, void )
258 UpdateStatus(false);
259 aModifyIdle.Stop();
262 IMPL_LINK_NOARG(SmEditWindow, CursorMoveTimerHdl, Timer *, void)
263 // every once in a while check cursor position (selection) of edit
264 // window and if it has changed (try to) set the formula-cursor
265 // according to that.
267 if (IsInlineEditEnabled())
268 return;
270 ESelection aNewSelection(GetSelection());
272 if (aNewSelection != aOldSelection)
274 SmViewShell *pView = rCmdBox.GetView();
275 if (pView)
277 // get row and column to look for
278 sal_Int32 nRow;
279 sal_uInt16 nCol;
280 SmGetLeftSelectionPart(aNewSelection, nRow, nCol);
281 nRow++;
282 nCol++;
283 pView->GetGraphicWindow().SetCursorPos(static_cast<sal_uInt16>(nRow), nCol);
284 aOldSelection = aNewSelection;
287 aCursorMoveIdle.Stop();
290 void SmEditWindow::Resize()
292 if (!pEditView)
293 CreateEditView();
295 if (pEditView)
297 // Resizes the edit engine to adjust to the size of the output area
298 const Size aSize( pEditView->GetOutputArea().GetSize() );
299 pEditView->GetEditEngine()->SetPaperSize(aSize);
301 pEditView->SetOutputArea(AdjustScrollBars());
302 pEditView->ShowCursor();
304 OSL_ENSURE( pEditView->GetEditEngine(), "EditEngine missing" );
305 const tools::Long nMaxVisAreaStart = pEditView->GetEditEngine()->GetTextHeight() -
306 pEditView->GetOutputArea().GetHeight();
307 if (pEditView->GetVisArea().Top() > nMaxVisAreaStart)
309 tools::Rectangle aVisArea(pEditView->GetVisArea() );
310 aVisArea.SetTop( std::max<tools::Long>(nMaxVisAreaStart, 0) );
311 aVisArea.SetSize(pEditView->GetOutputArea().GetSize());
312 pEditView->SetVisArea(aVisArea);
313 pEditView->ShowCursor();
315 InitScrollBars();
317 Invalidate();
320 void SmEditWindow::MouseButtonUp(const MouseEvent &rEvt)
322 if (pEditView)
323 pEditView->MouseButtonUp(rEvt);
324 else
325 Window::MouseButtonUp (rEvt);
327 if (!IsInlineEditEnabled())
328 CursorMoveTimerHdl(&aCursorMoveIdle);
329 InvalidateSlots();
332 void SmEditWindow::MouseButtonDown(const MouseEvent &rEvt)
334 if (pEditView)
335 pEditView->MouseButtonDown(rEvt);
336 else
337 Window::MouseButtonDown (rEvt);
339 GrabFocus();
342 void SmEditWindow::Command(const CommandEvent& rCEvt)
344 //pass alt press/release to parent impl
345 if (rCEvt.GetCommand() == CommandEventId::ModKeyChange)
347 Window::Command(rCEvt);
348 return;
351 bool bForwardEvt = true;
352 if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
354 GetParent()->ToTop();
356 Point aPoint = rCEvt.GetMousePosPixel();
357 SmViewShell* pViewSh = rCmdBox.GetView();
358 if (pViewSh)
359 pViewSh->GetViewFrame()->GetDispatcher()->ExecutePopup("edit", this, &aPoint);
360 bForwardEvt = false;
362 else if (rCEvt.GetCommand() == CommandEventId::Wheel)
363 bForwardEvt = !HandleWheelCommands( rCEvt );
365 if (bForwardEvt)
367 if (pEditView)
369 pEditView->Command(rCEvt);
370 UserPossiblyChangedText();
372 else
373 Window::Command (rCEvt);
377 bool SmEditWindow::HandleWheelCommands( const CommandEvent &rCEvt )
379 bool bCommandHandled = false; // true if the CommandEvent needs not
380 // to be passed on (because it has fully
381 // been taken care of).
383 const CommandWheelData* pWData = rCEvt.GetWheelData();
384 if (pWData)
386 if (CommandWheelMode::ZOOM == pWData->GetMode())
387 bCommandHandled = true; // no zooming in Command window
388 else
389 bCommandHandled = HandleScrollCommand( rCEvt, pHScrollBar.get(), pVScrollBar.get());
392 return bCommandHandled;
395 void SmEditWindow::KeyInput(const KeyEvent& rKEvt)
397 if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
399 bool bCallBase = true;
400 SfxViewShell* pViewShell = GetView();
401 if ( dynamic_cast<const SmViewShell *>(pViewShell) )
403 // Terminate possible InPlace mode
404 bCallBase = !pViewShell->Escape();
406 if ( bCallBase )
407 Window::KeyInput( rKEvt );
409 else
411 StartCursorMove();
413 bool autoClose = false;
414 if (!pEditView)
415 CreateEditView();
416 ESelection aSelection = pEditView->GetSelection();
417 // as we don't support RTL in Math, we need to swap values from selection when they were done
418 // in RTL form
419 aSelection.Adjust();
420 OUString selected = pEditView->GetEditEngine()->GetText(aSelection);
422 // Check is auto close brackets/braces is disabled
423 SmModule *pMod = SM_MOD();
424 if (pMod && !pMod->GetConfig()->IsAutoCloseBrackets())
425 autoClose = false;
426 else if (selected.trim() == "<?>")
427 autoClose = true;
428 else if (selected.isEmpty() && !aSelection.HasRange())
430 selected = pEditView->GetEditEngine()->GetText(aSelection.nEndPara);
431 if (!selected.isEmpty())
433 sal_Int32 index = selected.indexOf("\n", aSelection.nEndPos);
434 if (index != -1)
436 selected = selected.copy(index, sal_Int32(aSelection.nEndPos-index));
437 if (selected.trim().isEmpty())
438 autoClose = true;
440 else
442 sal_Int32 length = selected.getLength();
443 if (aSelection.nEndPos == length)
444 autoClose = true;
445 else
447 selected = selected.copy(aSelection.nEndPos);
448 if (selected.trim().isEmpty())
449 autoClose = true;
453 else
454 autoClose = true;
457 if ( !pEditView->PostKeyEvent(rKEvt) )
459 SmViewShell *pView = GetView();
460 if ( pView && !pView->KeyInput(rKEvt) )
462 // F1 (help) leads to the destruction of this
463 Flush();
464 if ( aModifyIdle.IsActive() )
465 aModifyIdle.Stop();
466 Window::KeyInput(rKEvt);
468 else
470 // SFX has maybe called a slot of the view and thus (because of a hack in SFX)
471 // set the focus to the view
472 SfxViewShell* pVShell = GetView();
473 if ( dynamic_cast<const SmViewShell *>(pVShell) &&
474 static_cast<SmViewShell*>(pVShell)->GetGraphicWindow().HasFocus() )
476 GrabFocus();
480 else
482 UserPossiblyChangedText();
485 // get the current char of the key event
486 sal_Unicode cCharCode = rKEvt.GetCharCode();
487 OUString sClose;
489 if (cCharCode == '{')
490 sClose = " }";
491 else if (cCharCode == '[')
492 sClose = " ]";
493 else if (cCharCode == '(')
494 sClose = " )";
496 // auto close the current character only when needed
497 if (!sClose.isEmpty() && autoClose)
499 pEditView->InsertText(sClose);
500 // position it at center of brackets
501 aSelection.nStartPos += 2;
502 aSelection.nEndPos = aSelection.nStartPos;
503 pEditView->SetSelection(aSelection);
506 InvalidateSlots();
510 void SmEditWindow::UserPossiblyChangedText()
512 // have doc-shell modified only for formula input/change and not
513 // cursor travelling and such things...
514 SmDocShell *pDocShell = GetDoc();
515 EditEngine *pEditEngine = GetEditEngine();
516 if (pDocShell && pEditEngine && pEditEngine->IsModified())
517 pDocShell->SetModified(true);
518 aModifyIdle.Start();
521 void SmEditWindow::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle& rRect)
523 if (!pEditView)
524 CreateEditView();
525 pEditView->Paint(rRect, &rRenderContext);
528 void SmEditWindow::CreateEditView()
530 EditEngine *pEditEngine = GetEditEngine();
532 //! pEditEngine and pEditView may be 0.
533 //! For example when the program is used by the document-converter
534 if (pEditView || !pEditEngine)
535 return;
537 pEditView.reset(new EditView(pEditEngine, this));
538 pEditEngine->InsertView( pEditView.get() );
540 if (!pVScrollBar)
541 pVScrollBar = VclPtr<ScrollBar>::Create(this, WinBits(WB_VSCROLL));
542 if (!pHScrollBar)
543 pHScrollBar = VclPtr<ScrollBar>::Create(this, WinBits(WB_HSCROLL));
544 if (!pScrollBox)
545 pScrollBox = VclPtr<ScrollBarBox>::Create(this);
546 pVScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
547 pHScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
548 pVScrollBar->EnableDrag();
549 pHScrollBar->EnableDrag();
551 pEditView->SetOutputArea(AdjustScrollBars());
553 ESelection eSelection;
555 pEditView->SetSelection(eSelection);
556 PaintImmediately();
557 pEditView->ShowCursor();
559 pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
560 SetPointer(pEditView->GetPointer());
562 SetScrollBarRanges();
566 IMPL_LINK_NOARG( SmEditWindow, EditStatusHdl, EditStatus&, void )
568 if (pEditView)
569 Resize();
572 IMPL_LINK( SmEditWindow, ScrollHdl, ScrollBar *, /*pScrollBar*/, void )
574 OSL_ENSURE(pEditView, "EditView missing");
575 if (pEditView)
577 pEditView->SetVisArea(tools::Rectangle(Point(pHScrollBar->GetThumbPos(),
578 pVScrollBar->GetThumbPos()),
579 pEditView->GetVisArea().GetSize()));
580 pEditView->Invalidate();
584 tools::Rectangle SmEditWindow::AdjustScrollBars()
586 const Size aOut( GetOutputSizePixel() );
587 tools::Rectangle aRect( Point(), aOut );
589 if (pVScrollBar && pHScrollBar && pScrollBox)
591 const tools::Long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
592 Point aPt( aRect.TopRight() ); aPt.AdjustX( -(nTmp -1) );
593 pVScrollBar->SetPosSizePixel( aPt, Size(nTmp, aOut.Height() - nTmp));
595 aPt = aRect.BottomLeft(); aPt.AdjustY( -(nTmp - 1) );
596 pHScrollBar->SetPosSizePixel( aPt, Size(aOut.Width() - nTmp, nTmp));
598 aPt.setX( pHScrollBar->GetSizePixel().Width() );
599 aPt.setY( pVScrollBar->GetSizePixel().Height() );
600 pScrollBox->SetPosSizePixel(aPt, Size(nTmp, nTmp ));
602 aRect.SetRight( aPt.X() - 2 );
603 aRect.SetBottom( aPt.Y() - 2 );
605 return aRect;
608 void SmEditWindow::SetScrollBarRanges()
610 // Extra method, not InitScrollBars, since it's also being used for EditEngine events
611 EditEngine *pEditEngine = GetEditEngine();
612 if (pVScrollBar && pHScrollBar && pEditEngine && pEditView)
614 tools::Long nTmp = pEditEngine->GetTextHeight();
615 pVScrollBar->SetRange(Range(0, nTmp));
616 pVScrollBar->SetThumbPos(pEditView->GetVisArea().Top());
618 nTmp = pEditEngine->GetPaperSize().Width();
619 pHScrollBar->SetRange(Range(0,nTmp));
620 pHScrollBar->SetThumbPos(pEditView->GetVisArea().Left());
624 void SmEditWindow::InitScrollBars()
626 if (!(pVScrollBar && pHScrollBar && pScrollBox && pEditView))
627 return;
629 const Size aOut( pEditView->GetOutputArea().GetSize() );
630 pVScrollBar->SetVisibleSize(aOut.Height());
631 pVScrollBar->SetPageSize(aOut.Height() * 8 / 10);
632 pVScrollBar->SetLineSize(aOut.Height() * 2 / 10);
634 pHScrollBar->SetVisibleSize(aOut.Width());
635 pHScrollBar->SetPageSize(aOut.Width() * 8 / 10);
636 pHScrollBar->SetLineSize(SCROLL_LINE );
638 SetScrollBarRanges();
640 pVScrollBar->Show();
641 pHScrollBar->Show();
642 pScrollBox->Show();
646 OUString SmEditWindow::GetText() const
648 OUString aText;
649 EditEngine *pEditEngine = const_cast< SmEditWindow* >(this)->GetEditEngine();
650 OSL_ENSURE( pEditEngine, "EditEngine missing" );
651 if (pEditEngine)
652 aText = pEditEngine->GetText();
653 return aText;
657 void SmEditWindow::SetText(const OUString& rText)
659 EditEngine *pEditEngine = GetEditEngine();
660 OSL_ENSURE( pEditEngine, "EditEngine missing" );
661 if (!pEditEngine || pEditEngine->IsModified())
662 return;
664 if (!pEditView)
665 CreateEditView();
667 ESelection eSelection = pEditView->GetSelection();
669 pEditEngine->SetText(rText);
670 pEditEngine->ClearModifyFlag();
672 // Restarting the timer here, prevents calling the handlers for other (currently inactive)
673 // math tasks
674 aModifyIdle.Start();
676 pEditView->SetSelection(eSelection);
680 void SmEditWindow::GetFocus()
682 Window::GetFocus();
684 if (mxAccessible.is())
686 // Note: will implicitly send the AccessibleStateType::FOCUSED event
687 ::accessibility::AccessibleTextHelper *pHelper = mxAccessible->GetTextHelper();
688 if (pHelper)
689 pHelper->SetFocus();
692 if (!pEditView)
693 CreateEditView();
694 EditEngine *pEditEngine = GetEditEngine();
695 if (pEditEngine)
696 pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
698 //Let SmViewShell know we got focus
699 if(GetView() && IsInlineEditEnabled())
700 GetView()->SetInsertIntoEditWindow(true);
704 void SmEditWindow::LoseFocus()
706 EditEngine *pEditEngine = GetEditEngine();
707 if (pEditEngine)
708 pEditEngine->SetStatusEventHdl( Link<EditStatus&,void>() );
710 Window::LoseFocus();
712 if (mxAccessible.is())
714 // Note: will implicitly send the AccessibleStateType::FOCUSED event
715 ::accessibility::AccessibleTextHelper *pHelper = mxAccessible->GetTextHelper();
716 if (pHelper)
717 pHelper->SetFocus(false);
722 bool SmEditWindow::IsAllSelected() const
724 bool bRes = false;
725 EditEngine *pEditEngine = const_cast<SmEditWindow *>(this)->GetEditEngine();
726 OSL_ENSURE( pEditView, "NULL pointer" );
727 OSL_ENSURE( pEditEngine, "NULL pointer" );
728 if (pEditEngine && pEditView)
730 ESelection eSelection( pEditView->GetSelection() );
731 sal_Int32 nParaCnt = pEditEngine->GetParagraphCount();
732 if (!(nParaCnt - 1))
734 sal_Int32 nTextLen = pEditEngine->GetText().getLength();
735 bRes = !eSelection.nStartPos && (eSelection.nEndPos == nTextLen - 1);
737 else
739 bRes = !eSelection.nStartPara && (eSelection.nEndPara == nParaCnt - 1);
742 return bRes;
745 void SmEditWindow::SelectAll()
747 OSL_ENSURE( pEditView, "NULL pointer" );
748 if (pEditView)
750 // ALL as last two parameters refers to the end of the text
751 pEditView->SetSelection( ESelection( 0, 0, EE_PARA_ALL, EE_TEXTPOS_ALL ) );
755 void SmEditWindow::MarkError(const Point &rPos)
757 OSL_ENSURE( pEditView, "EditView missing" );
758 if (pEditView)
760 const sal_uInt16 nCol = sal::static_int_cast< sal_uInt16 >(rPos.X());
761 const sal_uInt16 nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1);
763 pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol));
764 GrabFocus();
768 // Makes selection to next <?> symbol
769 void SmEditWindow::SelNextMark()
771 EditEngine *pEditEngine = GetEditEngine();
772 OSL_ENSURE( pEditView, "NULL pointer" );
773 OSL_ENSURE( pEditEngine, "NULL pointer" );
774 if (!pEditEngine || !pEditView)
775 return;
777 ESelection eSelection = pEditView->GetSelection();
778 sal_Int32 nPos = eSelection.nEndPos;
779 sal_Int32 nCounts = pEditEngine->GetParagraphCount();
781 while (eSelection.nEndPara < nCounts)
783 OUString aText = pEditEngine->GetText(eSelection.nEndPara);
784 nPos = aText.indexOf("<?>", nPos);
785 if (nPos != -1)
787 pEditView->SetSelection(ESelection(
788 eSelection.nEndPara, nPos, eSelection.nEndPara, nPos + 3));
789 break;
792 nPos = 0;
793 eSelection.nEndPara++;
797 void SmEditWindow::SelPrevMark()
799 EditEngine *pEditEngine = GetEditEngine();
800 OSL_ENSURE( pEditEngine, "NULL pointer" );
801 OSL_ENSURE( pEditView, "NULL pointer" );
802 if (!(pEditEngine && pEditView))
803 return;
805 ESelection eSelection = pEditView->GetSelection();
806 sal_Int32 nPara = eSelection.nStartPara;
807 sal_Int32 nMax = eSelection.nStartPos;
808 OUString aText(pEditEngine->GetText(nPara));
809 const OUString aMark("<?>");
810 sal_Int32 nPos;
812 while ( (nPos = aText.lastIndexOf(aMark, nMax)) < 0 )
814 if (--nPara < 0)
815 return;
816 aText = pEditEngine->GetText(nPara);
817 nMax = aText.getLength();
819 pEditView->SetSelection(ESelection(nPara, nPos, nPara, nPos + 3));
822 bool SmEditWindow::HasMark(const OUString& rText)
823 // returns true iff 'rText' contains a mark
825 return rText.indexOf("<?>") != -1;
828 void SmEditWindow::MouseMove(const MouseEvent &rEvt)
830 if (pEditView)
831 pEditView->MouseMove(rEvt);
834 sal_Int8 SmEditWindow::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
836 return DND_ACTION_NONE;
839 sal_Int8 SmEditWindow::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
841 return DND_ACTION_NONE;
844 ESelection SmEditWindow::GetSelection() const
846 // pointer may be 0 when reloading a document and the old view
847 // was already destroyed
848 //(OSL_ENSURE( pEditView, "NULL pointer" );
849 ESelection eSel;
850 if (pEditView)
851 eSel = pEditView->GetSelection();
852 return eSel;
855 void SmEditWindow::SetSelection(const ESelection &rSel)
857 OSL_ENSURE( pEditView, "NULL pointer" );
858 if (pEditView)
859 pEditView->SetSelection(rSel);
860 InvalidateSlots();
863 bool SmEditWindow::IsEmpty() const
865 EditEngine *pEditEngine = const_cast<SmEditWindow *>(this)->GetEditEngine();
866 bool bEmpty = ( pEditEngine && pEditEngine->GetTextLen() == 0 );
867 return bEmpty;
870 bool SmEditWindow::IsSelected() const
872 return pEditView && pEditView->HasSelection();
876 void SmEditWindow::UpdateStatus( bool bSetDocModified )
878 SmModule *pMod = SM_MOD();
879 if (pMod && pMod->GetConfig()->IsAutoRedraw())
880 Flush();
881 if ( bSetDocModified )
882 GetDoc()->SetModified();
885 void SmEditWindow::Cut()
887 OSL_ENSURE( pEditView, "EditView missing" );
888 if (pEditView)
890 pEditView->Cut();
891 UpdateStatus(true);
895 void SmEditWindow::Copy()
897 OSL_ENSURE( pEditView, "EditView missing" );
898 if (pEditView)
899 pEditView->Copy();
902 void SmEditWindow::Paste()
904 OSL_ENSURE( pEditView, "EditView missing" );
905 if (pEditView)
907 pEditView->Paste();
908 UpdateStatus(true);
912 void SmEditWindow::Delete()
914 OSL_ENSURE( pEditView, "EditView missing" );
915 if (pEditView)
917 pEditView->DeleteSelected();
918 UpdateStatus(true);
922 void SmEditWindow::InsertText(const OUString& rText)
924 OSL_ENSURE( pEditView, "EditView missing" );
925 if (!pEditView)
926 return;
928 // Note: Insertion of a space in front of commands is done here and
929 // in SmEditWindow::InsertCommand.
930 ESelection aSelection = pEditView->GetSelection();
931 OUString aCurrentFormula = pEditView->GetEditEngine()->GetText();
932 sal_Int32 nStartIndex = 0;
934 // get the start position (when we get a multi line formula)
935 for (sal_Int32 nParaPos = 0; nParaPos < aSelection.nStartPara; nParaPos++)
936 nStartIndex = aCurrentFormula.indexOf("\n", nStartIndex) + 1;
938 nStartIndex += aSelection.nStartPos;
940 // TODO: unify this function with the InsertCommand: The do the same thing for different
941 // callers
942 OUString string(rText);
944 OUString selected(pEditView->GetSelected());
945 // if we have text selected, use it in the first placeholder
946 if (!selected.isEmpty())
947 string = string.replaceFirst("<?>", selected);
949 // put a space before a new command if not in the beginning of a line
950 if (aSelection.nStartPos > 0 && aCurrentFormula[nStartIndex - 1] != ' ')
951 string = " " + string;
954 fdo#65588 - Elements Dock: Scrollbar moves into input window
955 This change "solves" the visual problem. But I don't think so
956 this is the best solution.
958 pVScrollBar->Hide();
959 pHScrollBar->Hide();
960 pEditView->InsertText(string);
961 AdjustScrollBars();
962 pVScrollBar->Show();
963 pHScrollBar->Show();
965 // Remember start of the selection and move the cursor there afterwards.
966 aSelection.nEndPara = aSelection.nStartPara;
967 if (HasMark(string))
969 aSelection.nEndPos = aSelection.nStartPos;
970 pEditView->SetSelection(aSelection);
971 SelNextMark();
973 else
974 { // set selection after inserted text
975 aSelection.nEndPos = aSelection.nStartPos + string.getLength();
976 aSelection.nStartPos = aSelection.nEndPos;
977 pEditView->SetSelection(aSelection);
980 aModifyIdle.Start();
981 StartCursorMove();
982 GrabFocus();
985 void SmEditWindow::Flush()
987 EditEngine *pEditEngine = GetEditEngine();
988 if (pEditEngine && pEditEngine->IsModified())
990 pEditEngine->ClearModifyFlag();
991 SmViewShell *pViewSh = rCmdBox.GetView();
992 if (pViewSh)
994 std::unique_ptr<SfxStringItem> pTextToFlush = std::make_unique<SfxStringItem>(SID_TEXT, GetText());
995 pViewSh->GetViewFrame()->GetDispatcher()->ExecuteList(
996 SID_TEXT, SfxCallMode::RECORD,
997 { pTextToFlush.get() });
1000 if (aCursorMoveIdle.IsActive())
1002 aCursorMoveIdle.Stop();
1003 CursorMoveTimerHdl(&aCursorMoveIdle);
1007 void SmEditWindow::DeleteEditView()
1009 if (pEditView)
1011 std::unique_ptr<EditEngine> xEditEngine(pEditView->GetEditEngine());
1012 if (xEditEngine)
1014 xEditEngine->SetStatusEventHdl( Link<EditStatus&,void>() );
1015 xEditEngine->RemoveView( pEditView.get() );
1017 pEditView.reset();
1021 uno::Reference< XAccessible > SmEditWindow::CreateAccessible()
1023 if (!mxAccessible.is())
1025 mxAccessible.set(new SmEditAccessible( this ));
1026 mxAccessible->Init();
1028 return uno::Reference< XAccessible >(mxAccessible.get());
1031 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */