bump product version to 7.6.3.2-android
[LibreOffice.git] / starmath / source / edit.cxx
blob0739e86436c2162683e63d0d395805c6f8983bcb
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/ptrstyle.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 <osl/diagnose.h>
35 #include <o3tl/string_view.hxx>
37 #include <edit.hxx>
38 #include <smmod.hxx>
39 #include <view.hxx>
40 #include <document.hxx>
41 #include <cfgitem.hxx>
42 #include <smediteng.hxx>
44 using namespace com::sun::star::accessibility;
45 using namespace com::sun::star;
48 void SmGetLeftSelectionPart(const ESelection &rSel,
49 sal_Int32 &nPara, sal_uInt16 &nPos)
50 // returns paragraph number and position of the selections left part
52 // compare start and end of selection and use the one that comes first
53 if ( rSel.nStartPara < rSel.nEndPara
54 || (rSel.nStartPara == rSel.nEndPara && rSel.nStartPos < rSel.nEndPos) )
55 { nPara = rSel.nStartPara;
56 nPos = rSel.nStartPos;
58 else
59 { nPara = rSel.nEndPara;
60 nPos = rSel.nEndPos;
64 SmEditTextWindow::SmEditTextWindow(SmEditWindow& rEditWindow)
65 : mrEditWindow(rEditWindow)
66 , aModifyIdle("SmEditWindow ModifyIdle")
67 , aCursorMoveIdle("SmEditWindow CursorMoveIdle")
69 SetAcceptsTab(true);
71 aModifyIdle.SetInvokeHandler(LINK(this, SmEditTextWindow, ModifyTimerHdl));
72 aModifyIdle.SetPriority(TaskPriority::LOWEST);
74 if (!SmViewShell::IsInlineEditEnabled())
76 aCursorMoveIdle.SetInvokeHandler(LINK(this, SmEditTextWindow, CursorMoveTimerHdl));
77 aCursorMoveIdle.SetPriority(TaskPriority::LOWEST);
81 SmEditTextWindow::~SmEditTextWindow()
83 aModifyIdle.Stop();
84 StartCursorMove();
87 EditEngine* SmEditTextWindow::GetEditEngine() const
89 SmDocShell *pDoc = mrEditWindow.GetDoc();
90 assert(pDoc);
91 return &pDoc->GetEditEngine();
94 void SmEditTextWindow::EditViewScrollStateChange()
96 mrEditWindow.SetScrollBarRanges();
99 void SmEditTextWindow::SetDrawingArea(weld::DrawingArea* pDrawingArea)
101 weld::CustomWidgetController::SetDrawingArea(pDrawingArea);
103 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
104 Color aBgColor = rStyleSettings.GetWindowColor();
106 OutputDevice& rDevice = pDrawingArea->get_ref_device();
107 rDevice.SetBackground(aBgColor);
109 SetHelpId(HID_SMA_COMMAND_WIN_EDIT);
111 EnableRTL(false);
113 EditEngine* pEditEngine = GetEditEngine();
115 m_xEditView.reset(new EditView(pEditEngine, nullptr));
116 m_xEditView->setEditViewCallbacks(this);
118 pEditEngine->InsertView(m_xEditView.get());
120 m_xEditView->SetOutputArea(mrEditWindow.AdjustScrollBars());
122 m_xEditView->SetBackgroundColor(aBgColor);
124 pDrawingArea->set_cursor(PointerStyle::Text);
126 pEditEngine->SetStatusEventHdl(LINK(this, SmEditTextWindow, EditStatusHdl));
128 InitAccessible();
130 //Apply zoom to smeditwindow text
131 if(GetEditView())
132 static_cast<SmEditEngine*>(GetEditEngine())->executeZoom(GetEditView());
135 SmEditWindow::SmEditWindow(SmCmdBoxWindow &rMyCmdBoxWin, weld::Builder& rBuilder)
136 : rCmdBox(rMyCmdBoxWin)
137 , mxScrolledWindow(rBuilder.weld_scrolled_window("scrolledwindow", true))
139 mxScrolledWindow->connect_vadjustment_changed(LINK(this, SmEditWindow, ScrollHdl));
141 CreateEditView(rBuilder);
144 SmEditWindow::~SmEditWindow() COVERITY_NOEXCEPT_FALSE
146 DeleteEditView();
147 mxScrolledWindow.reset();
150 weld::Window* SmEditWindow::GetFrameWeld() const
152 return rCmdBox.GetFrameWeld();
155 void SmEditTextWindow::StartCursorMove()
157 if (!SmViewShell::IsInlineEditEnabled())
158 aCursorMoveIdle.Stop();
161 void SmEditWindow::InvalidateSlots()
163 SfxBindings& rBind = GetView()->GetViewFrame().GetBindings();
164 rBind.Invalidate(SID_COPY);
165 rBind.Invalidate(SID_CUT);
166 rBind.Invalidate(SID_DELETE);
169 SmViewShell * SmEditWindow::GetView()
171 return rCmdBox.GetView();
174 SmDocShell * SmEditWindow::GetDoc()
176 SmViewShell *pView = rCmdBox.GetView();
177 return pView ? pView->GetDoc() : nullptr;
180 EditView * SmEditWindow::GetEditView() const
182 return mxTextControl ? mxTextControl->GetEditView() : nullptr;
185 EditEngine * SmEditWindow::GetEditEngine()
187 if (SmDocShell *pDoc = GetDoc())
188 return &pDoc->GetEditEngine();
189 return nullptr;
192 void SmEditTextWindow::StyleUpdated()
194 WeldEditView::StyleUpdated();
195 EditEngine *pEditEngine = GetEditEngine();
196 SmDocShell *pDoc = mrEditWindow.GetDoc();
198 if (pEditEngine && pDoc)
201 //! see also SmDocShell::GetEditEngine() !
203 const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
205 pDoc->UpdateEditEngineDefaultFonts();
206 pEditEngine->SetBackgroundColor(rStyleSettings.GetFieldColor());
207 pEditEngine->SetDefTab(sal_uInt16(GetTextWidth("XXXX")));
209 // forces new settings to be used
210 // unfortunately this resets the whole edit engine
211 // thus we need to save at least the text
212 OUString aTxt( pEditEngine->GetText() );
213 pEditEngine->Clear(); //incorrect font size
214 pEditEngine->SetText( aTxt );
216 Resize();
219 // Apply zoom to smeditwindow text
220 static_cast<SmEditEngine*>(GetEditEngine())->executeZoom(GetEditView());
223 IMPL_LINK_NOARG(SmEditTextWindow, ModifyTimerHdl, Timer *, void)
225 UpdateStatus(false);
226 aModifyIdle.Stop();
229 IMPL_LINK_NOARG(SmEditTextWindow, CursorMoveTimerHdl, Timer *, void)
230 // every once in a while check cursor position (selection) of edit
231 // window and if it has changed (try to) set the formula-cursor
232 // according to that.
234 if (SmViewShell::IsInlineEditEnabled())
235 return;
237 ESelection aNewSelection(GetSelection());
239 if (aNewSelection != aOldSelection)
241 if (SmViewShell *pViewSh = mrEditWindow.GetView())
243 // get row and column to look for
244 sal_Int32 nRow;
245 sal_uInt16 nCol;
246 SmGetLeftSelectionPart(aNewSelection, nRow, nCol);
247 pViewSh->GetGraphicWidget().SetCursorPos(static_cast<sal_uInt16>(nRow), nCol);
248 aOldSelection = aNewSelection;
251 aCursorMoveIdle.Stop();
254 bool SmEditTextWindow::MouseButtonUp(const MouseEvent &rEvt)
256 bool bRet = WeldEditView::MouseButtonUp(rEvt);
257 if (!SmViewShell::IsInlineEditEnabled())
258 CursorMoveTimerHdl(&aCursorMoveIdle);
259 mrEditWindow.InvalidateSlots();
260 return bRet;
263 bool SmEditTextWindow::Command(const CommandEvent& rCEvt)
265 // no zooming in Command window
266 const CommandWheelData* pWData = rCEvt.GetWheelData();
267 if (pWData && CommandWheelMode::ZOOM == pWData->GetMode())
268 return true;
270 //pass alt press/release to parent impl
271 if (rCEvt.GetCommand() == CommandEventId::ModKeyChange)
272 return false;
274 if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
276 ReleaseMouse();
277 SmCmdBoxWindow& rCmdBox = mrEditWindow.GetCmdBox();
278 rCmdBox.ShowContextMenu(rCmdBox.WidgetToWindowPos(*GetDrawingArea(), rCEvt.GetMousePosPixel()));
279 GrabFocus();
280 return true;
283 bool bConsumed = WeldEditView::Command(rCEvt);
284 if (bConsumed)
285 UserPossiblyChangedText();
286 return bConsumed;
289 bool SmEditTextWindow::KeyInput(const KeyEvent& rKEvt)
291 if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
293 bool bCallBase = true;
294 SfxViewShell* pViewShell = mrEditWindow.GetView();
295 if ( dynamic_cast<const SmViewShell *>(pViewShell) )
297 // Terminate possible InPlace mode
298 bCallBase = !pViewShell->Escape();
300 return !bCallBase;
303 StartCursorMove();
305 bool autoClose = false;
306 EditView* pEditView = GetEditView();
307 ESelection aSelection = pEditView->GetSelection();
308 // as we don't support RTL in Math, we need to swap values from selection when they were done
309 // in RTL form
310 aSelection.Adjust();
311 OUString selected = pEditView->GetEditEngine()->GetText(aSelection);
313 // Check is auto close brackets/braces is disabled
314 SmModule *pMod = SM_MOD();
315 if (pMod && !pMod->GetConfig()->IsAutoCloseBrackets())
316 autoClose = false;
317 else if (o3tl::trim(selected) == u"<?>")
318 autoClose = true;
319 else if (selected.isEmpty() && !aSelection.HasRange())
321 selected = pEditView->GetEditEngine()->GetText(aSelection.nEndPara);
322 if (!selected.isEmpty())
324 sal_Int32 index = selected.indexOf("\n", aSelection.nEndPos);
325 if (index != -1)
327 selected = selected.copy(index, sal_Int32(aSelection.nEndPos-index));
328 if (o3tl::trim(selected).empty())
329 autoClose = true;
331 else
333 sal_Int32 length = selected.getLength();
334 if (aSelection.nEndPos == length)
335 autoClose = true;
336 else
338 selected = selected.copy(aSelection.nEndPos);
339 if (o3tl::trim(selected).empty())
340 autoClose = true;
344 else
345 autoClose = true;
348 bool bConsumed = WeldEditView::KeyInput(rKEvt);
349 if (!bConsumed)
351 SmViewShell *pView = mrEditWindow.GetView();
352 if (pView)
353 bConsumed = pView->KeyInput(rKEvt);
354 if (pView && !bConsumed)
356 // F1 (help) leads to the destruction of this
357 Flush();
358 if ( aModifyIdle.IsActive() )
359 aModifyIdle.Stop();
361 else
363 // SFX has maybe called a slot of the view and thus (because of a hack in SFX)
364 // set the focus to the view
365 SmViewShell* pVShell = mrEditWindow.GetView();
366 if ( pVShell && pVShell->GetGraphicWidget().HasFocus() )
368 GrabFocus();
372 else
374 UserPossiblyChangedText();
377 // get the current char of the key event
378 sal_Unicode cCharCode = rKEvt.GetCharCode();
379 OUString sClose;
381 if (cCharCode == '{')
382 sClose = " }";
383 else if (cCharCode == '[')
384 sClose = " ]";
385 else if (cCharCode == '(')
386 sClose = " )";
388 // auto close the current character only when needed
389 if (!sClose.isEmpty() && autoClose)
391 pEditView->InsertText(sClose);
392 // position it at center of brackets
393 aSelection.nStartPos += 2;
394 aSelection.nEndPos = aSelection.nStartPos;
395 pEditView->SetSelection(aSelection);
398 mrEditWindow.InvalidateSlots();
399 return bConsumed;
402 void SmEditTextWindow::UserPossiblyChangedText()
404 // have doc-shell modified only for formula input/change and not
405 // cursor travelling and such things...
406 SmDocShell *pDocShell = mrEditWindow.GetDoc();
407 EditEngine *pEditEngine = GetEditEngine();
408 if (pDocShell && pEditEngine && pEditEngine->IsModified())
409 pDocShell->SetModified(true);
410 aModifyIdle.Start();
413 void SmEditWindow::CreateEditView(weld::Builder& rBuilder)
415 assert(!mxTextControl);
417 EditEngine *pEditEngine = GetEditEngine();
418 //! pEditEngine may be 0.
419 //! For example when the program is used by the document-converter
420 if (!pEditEngine)
421 return;
423 mxTextControl.reset(new SmEditTextWindow(*this));
424 mxTextControlWin.reset(new weld::CustomWeld(rBuilder, "editview", *mxTextControl));
426 SetScrollBarRanges();
429 IMPL_LINK_NOARG(SmEditTextWindow, EditStatusHdl, EditStatus&, void)
431 Resize();
434 IMPL_LINK(SmEditWindow, ScrollHdl, weld::ScrolledWindow&, rScrolledWindow, void)
436 if (EditView* pEditView = GetEditView())
438 pEditView->SetVisArea(tools::Rectangle(
439 Point(0,
440 rScrolledWindow.vadjustment_get_value()),
441 pEditView->GetVisArea().GetSize()));
442 pEditView->Invalidate();
446 tools::Rectangle SmEditWindow::AdjustScrollBars()
448 tools::Rectangle aRect(Point(), rCmdBox.GetOutputSizePixel());
450 if (mxScrolledWindow)
452 const auto nScrollSize = mxScrolledWindow->get_scroll_thickness();
453 const auto nMargin = nScrollSize + 2;
454 aRect.AdjustRight(-nMargin);
455 aRect.AdjustBottom(-nMargin);
458 return aRect;
461 void SmEditWindow::SetScrollBarRanges()
463 EditEngine *pEditEngine = GetEditEngine();
464 if (!pEditEngine)
465 return;
466 if (!mxScrolledWindow)
467 return;
468 EditView* pEditView = GetEditView();
469 if (!pEditView)
470 return;
472 int nVUpper = pEditEngine->GetTextHeight();
473 int nVCurrentDocPos = pEditView->GetVisArea().Top();
474 const Size aOut(pEditView->GetOutputArea().GetSize());
475 int nVStepIncrement = aOut.Height() * 2 / 10;
476 int nVPageIncrement = aOut.Height() * 8 / 10;
477 int nVPageSize = aOut.Height();
479 /* limit the page size to below nUpper because gtk's gtk_scrolled_window_start_deceleration has
480 effectively...
482 lower = gtk_adjustment_get_lower
483 upper = gtk_adjustment_get_upper - gtk_adjustment_get_page_size
485 and requires that upper > lower or the deceleration animation never ends
487 nVPageSize = std::min(nVPageSize, nVUpper);
489 mxScrolledWindow->vadjustment_configure(nVCurrentDocPos, 0, nVUpper,
490 nVStepIncrement, nVPageIncrement, nVPageSize);
493 OUString SmEditWindow::GetText() const
495 OUString aText;
496 EditEngine *pEditEngine = const_cast< SmEditWindow* >(this)->GetEditEngine();
497 OSL_ENSURE( pEditEngine, "EditEngine missing" );
498 if (pEditEngine)
499 aText = pEditEngine->GetText();
500 return aText;
503 void SmEditWindow::SetText(const OUString& rText)
505 if (!mxTextControl)
506 return;
507 mxTextControl->SetText(rText);
510 void SmEditWindow::Flush()
512 if (!mxTextControl)
513 return;
514 mxTextControl->Flush();
517 void SmEditWindow::GrabFocus()
519 if (!mxTextControl)
520 return;
521 mxTextControl->GrabFocus();
524 void SmEditTextWindow::SetText(const OUString& rText)
526 EditEngine *pEditEngine = GetEditEngine();
527 OSL_ENSURE( pEditEngine, "EditEngine missing" );
528 if (!pEditEngine || pEditEngine->IsModified())
529 return;
531 EditView* pEditView = GetEditView();
532 ESelection eSelection = pEditView->GetSelection();
534 pEditEngine->SetText(rText);
535 pEditEngine->ClearModifyFlag();
537 // Restarting the timer here, prevents calling the handlers for other (currently inactive)
538 // math tasks
539 aModifyIdle.Start();
541 // Apply zoom to smeditwindow text
542 static_cast<SmEditEngine*>(pEditView->GetEditEngine())->executeZoom(pEditView);
543 pEditView->SetSelection(eSelection);
546 void SmEditTextWindow::GetFocus()
548 WeldEditView::GetFocus();
550 EditEngine *pEditEngine = GetEditEngine();
551 if (pEditEngine)
552 pEditEngine->SetStatusEventHdl(LINK(this, SmEditTextWindow, EditStatusHdl));
554 //Let SmViewShell know we got focus
555 if (mrEditWindow.GetView() && SmViewShell::IsInlineEditEnabled())
556 mrEditWindow.GetView()->SetInsertIntoEditWindow(true);
559 void SmEditTextWindow::LoseFocus()
561 EditEngine *pEditEngine = GetEditEngine();
562 if (pEditEngine)
563 pEditEngine->SetStatusEventHdl( Link<EditStatus&,void>() );
565 WeldEditView::LoseFocus();
568 bool SmEditWindow::IsAllSelected() const
570 EditEngine *pEditEngine = const_cast<SmEditWindow *>(this)->GetEditEngine();
571 if (!pEditEngine)
572 return false;
573 EditView* pEditView = GetEditView();
574 if (!pEditView)
575 return false;
576 bool bRes = false;
577 ESelection eSelection( pEditView->GetSelection() );
578 sal_Int32 nParaCnt = pEditEngine->GetParagraphCount();
579 if (!(nParaCnt - 1))
581 sal_Int32 nTextLen = pEditEngine->GetText().getLength();
582 bRes = !eSelection.nStartPos && (eSelection.nEndPos == nTextLen - 1);
584 else
586 bRes = !eSelection.nStartPara && (eSelection.nEndPara == nParaCnt - 1);
588 return bRes;
591 void SmEditWindow::SelectAll()
593 if (EditView* pEditView = GetEditView())
595 // ALL as last two parameters refers to the end of the text
596 pEditView->SetSelection( ESelection( 0, 0, EE_PARA_ALL, EE_TEXTPOS_ALL ) );
600 void SmEditWindow::MarkError(const Point &rPos)
602 if (EditView* pEditView = GetEditView())
604 const sal_uInt16 nCol = sal::static_int_cast< sal_uInt16 >(rPos.X());
605 const sal_uInt16 nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1);
607 pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol));
608 GrabFocus();
612 void SmEditWindow::SelNextMark()
614 if (!mxTextControl)
615 return;
616 mxTextControl->SelNextMark();
619 // Makes selection to next <?> symbol
620 void SmEditTextWindow::SelNextMark()
622 EditEngine *pEditEngine = GetEditEngine();
623 if (!pEditEngine)
624 return;
625 EditView* pEditView = GetEditView();
626 if (!pEditView)
627 return;
629 ESelection eSelection = pEditView->GetSelection();
630 sal_Int32 nPos = eSelection.nEndPos;
631 sal_Int32 nCounts = pEditEngine->GetParagraphCount();
633 while (eSelection.nEndPara < nCounts)
635 OUString aText = pEditEngine->GetText(eSelection.nEndPara);
636 nPos = aText.indexOf("<?>", nPos);
637 if (nPos != -1)
639 pEditView->SetSelection(ESelection(
640 eSelection.nEndPara, nPos, eSelection.nEndPara, nPos + 3));
641 break;
644 nPos = 0;
645 eSelection.nEndPara++;
649 void SmEditWindow::SelPrevMark()
651 EditEngine *pEditEngine = GetEditEngine();
652 if (!pEditEngine)
653 return;
654 EditView* pEditView = GetEditView();
655 if (!pEditView)
656 return;
658 ESelection eSelection = pEditView->GetSelection();
659 sal_Int32 nPara = eSelection.nStartPara;
660 sal_Int32 nMax = eSelection.nStartPos;
661 OUString aText(pEditEngine->GetText(nPara));
662 static const OUStringLiteral aMark(u"<?>");
663 sal_Int32 nPos;
665 while ( (nPos = aText.lastIndexOf(aMark, nMax)) < 0 )
667 if (--nPara < 0)
668 return;
669 aText = pEditEngine->GetText(nPara);
670 nMax = aText.getLength();
672 pEditView->SetSelection(ESelection(nPara, nPos, nPara, nPos + 3));
675 // returns true iff 'rText' contains a mark
676 static bool HasMark(std::u16string_view rText)
678 return rText.find(u"<?>") != std::u16string_view::npos;
681 ESelection SmEditWindow::GetSelection() const
683 if (mxTextControl)
684 return mxTextControl->GetSelection();
685 return ESelection();
688 ESelection SmEditTextWindow::GetSelection() const
690 // pointer may be 0 when reloading a document and the old view
691 // was already destroyed
692 if (EditView* pEditView = GetEditView())
693 return pEditView->GetSelection();
694 return ESelection();
697 void SmEditWindow::SetSelection(const ESelection &rSel)
699 if (EditView* pEditView = GetEditView())
700 pEditView->SetSelection(rSel);
701 InvalidateSlots();
704 bool SmEditWindow::IsEmpty() const
706 EditEngine *pEditEngine = const_cast<SmEditWindow *>(this)->GetEditEngine();
707 bool bEmpty = ( pEditEngine && pEditEngine->GetTextLen() == 0 );
708 return bEmpty;
711 bool SmEditWindow::IsSelected() const
713 EditView* pEditView = GetEditView();
714 return pEditView && pEditView->HasSelection();
717 void SmEditTextWindow::UpdateStatus(bool bSetDocModified)
719 SmModule *pMod = SM_MOD();
720 if (pMod && pMod->GetConfig()->IsAutoRedraw())
721 Flush();
723 if (SmDocShell *pModifyDoc = bSetDocModified ? mrEditWindow.GetDoc() : nullptr)
724 pModifyDoc->SetModified();
726 static_cast<SmEditEngine*>(GetEditEngine())->executeZoom(GetEditView());
729 void SmEditWindow::UpdateStatus()
731 mxTextControl->UpdateStatus(/*bSetDocModified*/false);
734 void SmEditWindow::Cut()
736 if (mxTextControl)
738 mxTextControl->Cut();
739 mxTextControl->UpdateStatus(true);
743 void SmEditWindow::Copy()
745 if (mxTextControl)
746 mxTextControl->Copy();
749 void SmEditWindow::Paste()
751 if (mxTextControl)
753 mxTextControl->Paste();
754 mxTextControl->UpdateStatus(true);
758 void SmEditWindow::Delete()
760 if (mxTextControl)
762 mxTextControl->Delete();
763 mxTextControl->UpdateStatus(true);
767 void SmEditWindow::InsertText(const OUString& rText)
769 if (!mxTextControl)
770 return;
771 mxTextControl->InsertText(rText);
774 void SmEditTextWindow::InsertText(const OUString& rText)
776 EditView* pEditView = GetEditView();
777 if (!pEditView)
778 return;
780 // Note: Insertion of a space in front of commands is done here and
781 // in SmEditWindow::InsertCommand.
782 ESelection aSelection = pEditView->GetSelection();
783 OUString aCurrentFormula = pEditView->GetEditEngine()->GetText();
784 sal_Int32 nStartIndex = 0;
786 // get the start position (when we get a multi line formula)
787 for (sal_Int32 nParaPos = 0; nParaPos < aSelection.nStartPara; nParaPos++)
788 nStartIndex = aCurrentFormula.indexOf("\n", nStartIndex) + 1;
790 nStartIndex += aSelection.nStartPos;
792 // TODO: unify this function with the InsertCommand: The do the same thing for different
793 // callers
794 OUString string(rText);
796 OUString selected(pEditView->GetSelected());
797 // if we have text selected, use it in the first placeholder
798 if (!selected.isEmpty())
799 string = string.replaceFirst("<?>", selected);
801 // put a space before a new command if not in the beginning of a line
802 if (aSelection.nStartPos > 0 && aCurrentFormula[nStartIndex - 1] != ' ')
803 string = " " + string;
805 pEditView->InsertText(string);
807 // Remember start of the selection and move the cursor there afterwards.
808 aSelection.nEndPara = aSelection.nStartPara;
809 if (HasMark(string))
811 aSelection.nEndPos = aSelection.nStartPos;
812 pEditView->SetSelection(aSelection);
813 SelNextMark();
815 else
816 { // set selection after inserted text
817 aSelection.nEndPos = aSelection.nStartPos + string.getLength();
818 aSelection.nStartPos = aSelection.nEndPos;
819 pEditView->SetSelection(aSelection);
822 aModifyIdle.Start();
823 StartCursorMove();
825 GrabFocus();
828 void SmEditTextWindow::Flush()
830 EditEngine *pEditEngine = GetEditEngine();
831 if (pEditEngine && pEditEngine->IsModified())
833 pEditEngine->ClearModifyFlag();
834 if (SmViewShell *pViewSh = mrEditWindow.GetView())
836 SfxStringItem aTextToFlush(SID_TEXT, GetText());
837 pViewSh->GetViewFrame().GetDispatcher()->ExecuteList(
838 SID_TEXT, SfxCallMode::RECORD,
839 { &aTextToFlush });
842 if (aCursorMoveIdle.IsActive())
844 aCursorMoveIdle.Stop();
845 CursorMoveTimerHdl(&aCursorMoveIdle);
849 void SmEditWindow::DeleteEditView()
851 if (EditView* pEditView = GetEditView())
853 if (EditEngine* pEditEngine = pEditView->GetEditEngine())
855 pEditEngine->SetStatusEventHdl( Link<EditStatus&,void>() );
856 pEditEngine->RemoveView(pEditView);
858 mxTextControlWin.reset();
859 mxTextControl.reset();
863 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */