Bump version to 5.0-14
[LibreOffice.git] / starmath / source / edit.cxx
blobe42749eba4f9919d01fed1ec4902dc366af38aef
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 <com/sun/star/accessibility/XAccessible.hpp>
21 #include <com/sun/star/accessibility/AccessibleEventObject.hpp>
22 #include <com/sun/star/accessibility/AccessibleEventId.hpp>
23 #include <com/sun/star/accessibility/AccessibleStateType.hpp>
24 #include <toolkit/helper/vclunohelper.hxx>
27 #include "starmath.hrc"
29 #include <vcl/menu.hxx>
30 #include <vcl/settings.hxx>
32 #include <editeng/editview.hxx>
33 #include <editeng/editeng.hxx>
34 #include <editeng/editstat.hxx>
35 #include <editeng/eeitem.hxx>
36 #include <sfx2/dispatch.hxx>
37 #include <svl/intitem.hxx>
38 #include <svl/itempool.hxx>
39 #include <svl/stritem.hxx>
40 #include <editeng/fhgtitem.hxx>
41 #include <editeng/wghtitem.hxx>
42 #include <editeng/lrspitem.hxx>
43 #include <svl/itemset.hxx>
44 #include <editeng/fontitem.hxx>
45 #include <sfx2/viewfrm.hxx>
47 #include "edit.hxx"
48 #include "view.hxx"
49 #include "document.hxx"
50 #include "config.hxx"
51 #include "accessibility.hxx"
52 #include <memory>
54 #define SCROLL_LINE 24
57 using namespace com::sun::star::accessibility;
58 using namespace com::sun::star;
59 using namespace com::sun::star::uno;
64 void SmGetLeftSelectionPart(const ESelection &rSel,
65 sal_Int32 &nPara, sal_uInt16 &nPos)
66 // returns paragraph number and position of the selections left part
68 // compare start and end of selection and use the one that comes first
69 if ( rSel.nStartPara < rSel.nEndPara
70 || (rSel.nStartPara == rSel.nEndPara && rSel.nStartPos < rSel.nEndPos) )
71 { nPara = rSel.nStartPara;
72 nPos = rSel.nStartPos;
74 else
75 { nPara = rSel.nEndPara;
76 nPos = rSel.nEndPos;
80 bool SmEditWindow::IsInlineEditEnabled()
82 SmViewShell *pView = GetView();
83 return pView && pView->IsInlineEditEnabled();
88 SmEditWindow::SmEditWindow( SmCmdBoxWindow &rMyCmdBoxWin ) :
89 Window (&rMyCmdBoxWin),
90 DropTargetHelper ( this ),
91 pAccessible (0),
92 rCmdBox (rMyCmdBoxWin)
94 SetHelpId(HID_SMA_COMMAND_WIN_EDIT);
95 SetMapMode(MAP_PIXEL);
97 // Even RTL languages don't use RTL for math
98 EnableRTL( false );
100 ApplyColorConfigValues( SM_MOD()->GetColorConfig() );
102 // compare DataChanged
103 SetBackground( GetSettings().GetStyleSettings().GetWindowColor() );
105 aModifyIdle.SetIdleHdl(LINK(this, SmEditWindow, ModifyTimerHdl));
106 aModifyIdle.SetPriority(SchedulerPriority::LOWEST);
108 if (!IsInlineEditEnabled())
110 aCursorMoveIdle.SetIdleHdl(LINK(this, SmEditWindow, CursorMoveTimerHdl));
111 aCursorMoveIdle.SetPriority(SchedulerPriority::LOWEST);
114 // if not called explicitly the this edit window within the
115 // command window will just show an empty gray panel.
116 Show();
120 SmEditWindow::~SmEditWindow()
122 disposeOnce();
125 void SmEditWindow::dispose()
127 aModifyIdle.Stop();
129 StartCursorMove();
131 // clean up of classes used for accessibility
132 // must be done before EditView (and thus EditEngine) is no longer
133 // available for those classes.
134 if (pAccessible)
136 pAccessible->ClearWin(); // make Accessible defunctional
137 pAccessible = NULL;
138 xAccessible.clear();
140 // Note: memory for pAccessible will be freed when the reference
141 // xAccessible is released. FIXME: horribly redundant lifecycle ! ...
143 if (pEditView)
145 EditEngine *pEditEngine = pEditView->GetEditEngine();
146 if (pEditEngine)
148 pEditEngine->SetStatusEventHdl( Link<>() );
149 pEditEngine->RemoveView( pEditView.get() );
151 pEditView.reset();
154 pHScrollBar.disposeAndClear();
155 pVScrollBar.disposeAndClear();
156 pScrollBox.disposeAndClear();
158 vcl::Window::dispose();
161 void SmEditWindow::StartCursorMove()
163 if (!IsInlineEditEnabled())
164 aCursorMoveIdle.Stop();
167 void SmEditWindow::InvalidateSlots()
169 SfxBindings& rBind = GetView()->GetViewFrame()->GetBindings();
170 rBind.Invalidate(SID_COPY);
171 rBind.Invalidate(SID_CUT);
172 rBind.Invalidate(SID_DELETE);
175 SmViewShell * SmEditWindow::GetView()
177 return rCmdBox.GetView();
181 SmDocShell * SmEditWindow::GetDoc()
183 SmViewShell *pView = rCmdBox.GetView();
184 return pView ? pView->GetDoc() : 0;
187 EditView * SmEditWindow::GetEditView()
189 return pEditView.get();
192 EditEngine * SmEditWindow::GetEditEngine()
194 EditEngine *pEditEng = 0;
195 if (pEditView)
196 pEditEng = pEditView->GetEditEngine();
197 else
199 SmDocShell *pDoc = GetDoc();
200 if (pDoc)
201 pEditEng = &pDoc->GetEditEngine();
203 return pEditEng;
207 SfxItemPool * SmEditWindow::GetEditEngineItemPool()
209 SmDocShell *pDoc = GetDoc();
210 return pDoc ? &pDoc->GetEditEngineItemPool() : 0;
213 void SmEditWindow::ApplyColorConfigValues( const svtools::ColorConfig &rColorCfg )
215 // Note: SetBackground still done in SmEditWindow::DataChanged
216 #if OSL_DEBUG_LEVEL > 1
217 // ColorData nVal = rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor;
218 #endif
219 SetTextColor( rColorCfg.GetColorValue(svtools::FONTCOLOR).nColor );
220 Invalidate();
223 void SmEditWindow::DataChanged( const DataChangedEvent& )
225 const StyleSettings aSettings( GetSettings().GetStyleSettings() );
227 // FIXME RenderContext
229 ApplyColorConfigValues( SM_MOD()->GetColorConfig() );
230 SetBackground( aSettings.GetWindowColor() );
232 // edit fields in other Applications use this font instead of
233 // the application font thus we use this one too
234 SetPointFont(*this, aSettings.GetFieldFont() /*aSettings.GetAppFont()*/);
236 EditEngine *pEditEngine = GetEditEngine();
237 SfxItemPool *pEditEngineItemPool = GetEditEngineItemPool();
239 if (pEditEngine && pEditEngineItemPool)
242 //! see also SmDocShell::GetEditEngine() !
245 pEditEngine->SetDefTab(sal_uInt16(GetTextWidth(OUString("XXXX"))));
247 SetEditEngineDefaultFonts(*pEditEngineItemPool);
249 // forces new settings to be used
250 // unfortunately this resets the whole edit engine
251 // thus we need to save at least the text
252 OUString aTxt( pEditEngine->GetText( LINEEND_LF ) );
253 pEditEngine->Clear(); //incorrect font size
254 pEditEngine->SetText( aTxt );
257 AdjustScrollBars();
258 Resize();
261 IMPL_LINK_NOARG_TYPED( SmEditWindow, ModifyTimerHdl, Idle *, void )
263 UpdateStatus();
264 aModifyIdle.Stop();
267 IMPL_LINK_NOARG_TYPED(SmEditWindow, CursorMoveTimerHdl, Idle *, void)
268 // every once in a while check cursor position (selection) of edit
269 // window and if it has changed (try to) set the formula-cursor
270 // according to that.
272 if (IsInlineEditEnabled())
273 return;
275 ESelection aNewSelection(GetSelection());
277 if (!aNewSelection.IsEqual(aOldSelection))
279 SmViewShell *pView = rCmdBox.GetView();
280 if (pView)
282 // get row and column to look for
283 sal_Int32 nRow;
284 sal_uInt16 nCol;
285 SmGetLeftSelectionPart(aNewSelection, nRow, nCol);
286 nRow++;
287 nCol++;
288 pView->GetGraphicWindow().SetCursorPos(static_cast<sal_uInt16>(nRow), nCol);
289 aOldSelection = aNewSelection;
292 aCursorMoveIdle.Stop();
295 void SmEditWindow::Resize()
297 if (!pEditView)
298 CreateEditView();
300 if (pEditView)
302 pEditView->SetOutputArea(AdjustScrollBars());
303 pEditView->ShowCursor();
305 OSL_ENSURE( pEditView->GetEditEngine(), "EditEngine missing" );
306 const long nMaxVisAreaStart = pEditView->GetEditEngine()->GetTextHeight() -
307 pEditView->GetOutputArea().GetHeight();
308 if (pEditView->GetVisArea().Top() > nMaxVisAreaStart)
310 Rectangle aVisArea(pEditView->GetVisArea() );
311 aVisArea.Top() = (nMaxVisAreaStart > 0 ) ? nMaxVisAreaStart : 0;
312 aVisArea.SetSize(pEditView->GetOutputArea().GetSize());
313 pEditView->SetVisArea(aVisArea);
314 pEditView->ShowCursor();
316 InitScrollBars();
318 Invalidate();
321 void SmEditWindow::MouseButtonUp(const MouseEvent &rEvt)
323 if (pEditView)
324 pEditView->MouseButtonUp(rEvt);
325 else
326 Window::MouseButtonUp (rEvt);
328 if (!IsInlineEditEnabled())
329 CursorMoveTimerHdl(&aCursorMoveIdle);
330 InvalidateSlots();
333 void SmEditWindow::MouseButtonDown(const MouseEvent &rEvt)
335 if (pEditView)
336 pEditView->MouseButtonDown(rEvt);
337 else
338 Window::MouseButtonDown (rEvt);
340 GrabFocus();
343 void SmEditWindow::Command(const CommandEvent& rCEvt)
345 bool bForwardEvt = true;
346 if (rCEvt.GetCommand() == CommandEventId::ContextMenu)
348 GetParent()->ToTop();
350 Point aPoint = rCEvt.GetMousePosPixel();
351 std::unique_ptr<PopupMenu> xPopupMenu(new PopupMenu(SmResId(RID_COMMANDMENU)));
353 // added for replaceability of context menus
354 Menu* pMenu = NULL;
355 ::com::sun::star::ui::ContextMenuExecuteEvent aEvent;
356 aEvent.SourceWindow = VCLUnoHelper::GetInterface( this );
357 aEvent.ExecutePosition.X = aPoint.X();
358 aEvent.ExecutePosition.Y = aPoint.Y();
359 OUString sDummy;
360 if ( GetView()->TryContextMenuInterception( *xPopupMenu, sDummy, pMenu, aEvent ) )
362 if ( pMenu )
364 xPopupMenu.reset(static_cast<PopupMenu*>(pMenu));
368 xPopupMenu->SetSelectHdl(LINK(this, SmEditWindow, MenuSelectHdl));
370 xPopupMenu->Execute( this, aPoint );
371 bForwardEvt = false;
373 else if (rCEvt.GetCommand() == CommandEventId::Wheel)
374 bForwardEvt = !HandleWheelCommands( rCEvt );
376 if (bForwardEvt)
378 if (pEditView)
379 pEditView->Command( rCEvt );
380 else
381 Window::Command (rCEvt);
386 bool SmEditWindow::HandleWheelCommands( const CommandEvent &rCEvt )
388 bool bCommandHandled = false; // true if the CommandEvent needs not
389 // to be passed on (because it has fully
390 // been taken care of).
392 const CommandWheelData* pWData = rCEvt.GetWheelData();
393 if (pWData)
395 if (CommandWheelMode::ZOOM == pWData->GetMode())
396 bCommandHandled = true; // no zooming in Command window
397 else
398 bCommandHandled = HandleScrollCommand( rCEvt, pHScrollBar.get(), pVScrollBar.get());
401 return bCommandHandled;
405 IMPL_LINK( SmEditWindow, MenuSelectHdl, Menu *, pMenu )
407 SmViewShell *pViewSh = rCmdBox.GetView();
408 if (pViewSh)
409 pViewSh->GetViewFrame()->GetDispatcher()->Execute(
410 SID_INSERTCOMMAND, SfxCallMode::RECORD,
411 new SfxInt16Item(SID_INSERTCOMMAND, pMenu->GetCurItemId()), 0L);
412 return 0;
415 void SmEditWindow::KeyInput(const KeyEvent& rKEvt)
417 if (rKEvt.GetKeyCode().GetCode() == KEY_ESCAPE)
419 bool bCallBase = true;
420 SfxViewShell* pViewShell = GetView();
421 if ( pViewShell && pViewShell->ISA(SmViewShell) )
423 // Terminate possible InPlace mode
424 bCallBase = !pViewShell->Escape();
426 if ( bCallBase )
427 Window::KeyInput( rKEvt );
429 else
431 StartCursorMove();
433 bool autoClose = false;
434 if (!pEditView)
435 CreateEditView();
436 ESelection aSelection = pEditView->GetSelection();
437 // as we don't support RTL in Math, we need to swap values from selection when they were done
438 // in RTL form
439 aSelection.Adjust();
440 OUString selected = pEditView->GetEditEngine()->GetText(aSelection);
442 if (selected.trim() == "<?>")
443 autoClose = true;
444 else if (selected.isEmpty() && !aSelection.HasRange())
446 selected = pEditView->GetEditEngine()->GetText(aSelection.nEndPara);
447 if (!selected.isEmpty())
449 sal_Int32 index = selected.indexOf("\n", aSelection.nEndPos);
450 if (index != -1)
452 selected = selected.copy(index, sal_Int32(aSelection.nEndPos-index));
453 if (selected.trim().isEmpty())
454 autoClose = true;
456 else
458 sal_Int32 length = selected.getLength();
459 if (aSelection.nEndPos == length)
460 autoClose = true;
461 else
463 selected = selected.copy(aSelection.nEndPos);
464 if (selected.trim().isEmpty())
465 autoClose = true;
469 else
470 autoClose = true;
473 if ( !pEditView->PostKeyEvent(rKEvt) )
475 SmViewShell *pView = GetView();
476 if ( pView && !pView->KeyInput(rKEvt) )
478 // F1 (help) leads to the destruction of this
479 Flush();
480 if ( aModifyIdle.IsActive() )
481 aModifyIdle.Stop();
482 Window::KeyInput(rKEvt);
484 else
486 // SFX has maybe called a slot of the view and thus (because of a hack in SFX)
487 // set the focus to the view
488 SfxViewShell* pVShell = GetView();
489 if ( pVShell && pVShell->ISA(SmViewShell) &&
490 static_cast<SmViewShell*>(pVShell)->GetGraphicWindow().HasFocus() )
492 GrabFocus();
496 else
498 // have doc-shell modified only for formula input/change and not
499 // cursor travelling and such things...
500 SmDocShell *pDocShell = GetDoc();
501 EditEngine *pEditEngine = GetEditEngine();
502 if (pDocShell && pEditEngine)
503 pDocShell->SetModified(pEditEngine->IsModified());
504 aModifyIdle.Start();
507 // get the current char of the key event
508 sal_Unicode cCharCode = rKEvt.GetCharCode();
509 OUString sClose;
511 if (cCharCode == '{')
512 sClose = " }";
513 else if (cCharCode == '[')
514 sClose = " ]";
515 else if (cCharCode == '(')
516 sClose = " )";
518 // auto close the current character only when needed
519 if (!sClose.isEmpty() && autoClose)
521 pEditView->InsertText(sClose);
522 // position it at center of brackets
523 aSelection.nStartPos += 2;
524 aSelection.nEndPos = aSelection.nStartPos;
525 pEditView->SetSelection(aSelection);
528 InvalidateSlots();
532 void SmEditWindow::Paint(vcl::RenderContext& rRenderContext, const Rectangle& rRect)
534 if (!pEditView)
535 CreateEditView();
536 pEditView->Paint(rRect, &rRenderContext);
539 void SmEditWindow::CreateEditView()
541 EditEngine *pEditEngine = GetEditEngine();
543 //! pEditEngine and pEditView may be 0.
544 //! For example when the program is used by the document-converter
545 if (!pEditView && pEditEngine)
547 pEditView.reset(new EditView(pEditEngine, this));
548 pEditEngine->InsertView( pEditView.get() );
550 if (!pVScrollBar)
551 pVScrollBar = VclPtr<ScrollBar>::Create(this, WinBits(WB_VSCROLL));
552 if (!pHScrollBar)
553 pHScrollBar = VclPtr<ScrollBar>::Create(this, WinBits(WB_HSCROLL));
554 if (!pScrollBox)
555 pScrollBox = VclPtr<ScrollBarBox>::Create(this);
556 pVScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
557 pHScrollBar->SetScrollHdl(LINK(this, SmEditWindow, ScrollHdl));
558 pVScrollBar->EnableDrag( true );
559 pHScrollBar->EnableDrag( true );
561 pEditView->SetOutputArea(AdjustScrollBars());
563 ESelection eSelection;
565 pEditView->SetSelection(eSelection);
566 Update();
567 pEditView->ShowCursor(true, true);
569 pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
570 SetPointer(pEditView->GetPointer());
572 SetScrollBarRanges();
577 IMPL_LINK( SmEditWindow, EditStatusHdl, EditStatus *, /*pStat*/ )
579 if (!pEditView)
580 return 1;
581 else
583 Resize();
584 return 0;
588 IMPL_LINK( SmEditWindow, ScrollHdl, ScrollBar *, /*pScrollBar*/ )
590 OSL_ENSURE(pEditView, "EditView missing");
591 if (pEditView)
593 pEditView->SetVisArea(Rectangle(Point(pHScrollBar->GetThumbPos(),
594 pVScrollBar->GetThumbPos()),
595 pEditView->GetVisArea().GetSize()));
596 pEditView->Invalidate();
598 return 0;
601 Rectangle SmEditWindow::AdjustScrollBars()
603 const Size aOut( GetOutputSizePixel() );
604 Point aPoint;
605 Rectangle aRect( aPoint, aOut );
607 if (pVScrollBar && pHScrollBar && pScrollBox)
609 const long nTmp = GetSettings().GetStyleSettings().GetScrollBarSize();
610 Point aPt( aRect.TopRight() ); aPt.X() -= nTmp -1L;
611 pVScrollBar->SetPosSizePixel( aPt, Size(nTmp, aOut.Height() - nTmp));
613 aPt = aRect.BottomLeft(); aPt.Y() -= nTmp - 1L;
614 pHScrollBar->SetPosSizePixel( aPt, Size(aOut.Width() - nTmp, nTmp));
616 aPt.X() = pHScrollBar->GetSizePixel().Width();
617 aPt.Y() = pVScrollBar->GetSizePixel().Height();
618 pScrollBox->SetPosSizePixel(aPt, Size(nTmp, nTmp ));
620 aRect.Right() = aPt.X() - 2;
621 aRect.Bottom() = aPt.Y() - 2;
623 return aRect;
626 void SmEditWindow::SetScrollBarRanges()
628 // Extra method, not InitScrollBars, since it's also being used for EditEngine events
629 EditEngine *pEditEngine = GetEditEngine();
630 if (pVScrollBar && pHScrollBar && pEditEngine && pEditView)
632 long nTmp = pEditEngine->GetTextHeight();
633 pVScrollBar->SetRange(Range(0, nTmp));
634 pVScrollBar->SetThumbPos(pEditView->GetVisArea().Top());
636 nTmp = pEditEngine->GetPaperSize().Width();
637 pHScrollBar->SetRange(Range(0,nTmp));
638 pHScrollBar->SetThumbPos(pEditView->GetVisArea().Left());
642 void SmEditWindow::InitScrollBars()
644 if (pVScrollBar && pHScrollBar && pScrollBox && pEditView)
646 const Size aOut( pEditView->GetOutputArea().GetSize() );
647 pVScrollBar->SetVisibleSize(aOut.Height());
648 pVScrollBar->SetPageSize(aOut.Height() * 8 / 10);
649 pVScrollBar->SetLineSize(aOut.Height() * 2 / 10);
651 pHScrollBar->SetVisibleSize(aOut.Width());
652 pHScrollBar->SetPageSize(aOut.Width() * 8 / 10);
653 pHScrollBar->SetLineSize(SCROLL_LINE );
655 SetScrollBarRanges();
657 pVScrollBar->Show();
658 pHScrollBar->Show();
659 pScrollBox->Show();
664 OUString SmEditWindow::GetText() const
666 OUString aText;
667 EditEngine *pEditEngine = const_cast< SmEditWindow* >(this)->GetEditEngine();
668 OSL_ENSURE( pEditEngine, "EditEngine missing" );
669 if (pEditEngine)
670 aText = pEditEngine->GetText( LINEEND_LF );
671 return aText;
675 void SmEditWindow::SetText(const OUString& rText)
677 EditEngine *pEditEngine = GetEditEngine();
678 OSL_ENSURE( pEditEngine, "EditEngine missing" );
679 if (pEditEngine && !pEditEngine->IsModified())
681 if (!pEditView)
682 CreateEditView();
684 ESelection eSelection = pEditView->GetSelection();
686 pEditEngine->SetText(rText);
687 pEditEngine->ClearModifyFlag();
689 // Restarting the timer here, prevents calling the handlers for other (currently inactive)
690 // math tasks
691 aModifyIdle.Start();
693 pEditView->SetSelection(eSelection);
698 void SmEditWindow::GetFocus()
700 Window::GetFocus();
702 if (xAccessible.is())
704 // Note: will implicitly send the AccessibleStateType::FOCUSED event
705 ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper();
706 if (pHelper)
707 pHelper->SetFocus(true);
710 if (!pEditView)
711 CreateEditView();
712 EditEngine *pEditEngine = GetEditEngine();
713 if (pEditEngine)
714 pEditEngine->SetStatusEventHdl( LINK(this, SmEditWindow, EditStatusHdl) );
716 //Let SmViewShell know we got focus
717 if(GetView() && IsInlineEditEnabled())
718 GetView()->SetInsertIntoEditWindow(true);
722 void SmEditWindow::LoseFocus()
724 EditEngine *pEditEngine = GetEditEngine();
725 if (pEditEngine)
726 pEditEngine->SetStatusEventHdl( Link<>() );
728 Window::LoseFocus();
730 if (xAccessible.is())
732 // Note: will implicitly send the AccessibleStateType::FOCUSED event
733 ::accessibility::AccessibleTextHelper *pHelper = pAccessible->GetTextHelper();
734 if (pHelper)
735 pHelper->SetFocus(false);
740 bool SmEditWindow::IsAllSelected() const
742 bool bRes = false;
743 EditEngine *pEditEngine = (const_cast<SmEditWindow *>(this))->GetEditEngine();
744 OSL_ENSURE( pEditView, "NULL pointer" );
745 OSL_ENSURE( pEditEngine, "NULL pointer" );
746 if (pEditEngine && pEditView)
748 ESelection eSelection( pEditView->GetSelection() );
749 sal_Int32 nParaCnt = pEditEngine->GetParagraphCount();
750 if (!(nParaCnt - 1))
752 sal_Int32 nTextLen = pEditEngine->GetText( LINEEND_LF ).getLength();
753 bRes = !eSelection.nStartPos && (eSelection.nEndPos == nTextLen - 1);
755 else
757 bRes = !eSelection.nStartPara && (eSelection.nEndPara == nParaCnt - 1);
760 return bRes;
763 void SmEditWindow::SelectAll()
765 OSL_ENSURE( pEditView, "NULL pointer" );
766 if (pEditView)
768 // ALL as last two parameters refers to the end of the text
769 pEditView->SetSelection( ESelection( 0, 0, EE_PARA_ALL, EE_TEXTPOS_ALL ) );
773 void SmEditWindow::InsertCommand(sal_uInt16 nCommand)
775 OSL_ENSURE( pEditView, "EditView missing" );
776 if (pEditView)
778 ESelection aSelection = pEditView->GetSelection();
780 OSL_ENSURE( pEditView, "NULL pointer" );
781 OUString aText = SM_RESSTR(nCommand);
783 OUString aCurrentFormula = pEditView->GetEditEngine()->GetText();
784 sal_Int32 nStartIndex = 0;
785 sal_Int32 nEndIndex = 0;
787 // get the start position (when we get a multi line formula)
788 for (sal_Int32 nParaPos = 0; nParaPos < aSelection.nStartPara; nParaPos++)
789 nStartIndex = aCurrentFormula.indexOf("\n", nStartIndex) + 1;
791 nStartIndex += aSelection.nStartPos;
793 // get the end position (when we get a multi line formula)
794 for (sal_Int32 nParaPos = 0; nParaPos < aSelection.nEndPara; nParaPos++)
795 nEndIndex = aCurrentFormula.indexOf("\n", nEndIndex) + 1;
797 nEndIndex += aSelection.nEndPos;
799 // remove right space of current symbol if there already is one
800 if (nEndIndex < aCurrentFormula.getLength() &&
801 aCurrentFormula[nEndIndex] == ' ')
802 aText = aText.trim();
804 // put a space before a new command if not in the beginning of a line
805 if (aSelection.nStartPos > 0 && aCurrentFormula[nStartIndex - 1] != ' ')
806 aText = " " + aText;
808 pEditView->InsertText(aText);
810 // Remember start of the selection and move the cursor there afterwards.
811 aSelection.nEndPara = aSelection.nStartPara;
812 if (HasMark(aText))
814 aSelection.nEndPos = aSelection.nStartPos;
815 pEditView->SetSelection(aSelection);
816 SelNextMark();
818 else
819 { // set selection after inserted text
820 aSelection.nEndPos = aSelection.nStartPos + aText.getLength();
821 aSelection.nStartPos = aSelection.nEndPos;
822 pEditView->SetSelection(aSelection);
825 aModifyIdle.Start();
826 StartCursorMove();
827 GrabFocus();
831 void SmEditWindow::MarkError(const Point &rPos)
833 OSL_ENSURE( pEditView, "EditView missing" );
834 if (pEditView)
836 const sal_uInt16 nCol = sal::static_int_cast< sal_uInt16 >(rPos.X());
837 const sal_uInt16 nRow = sal::static_int_cast< sal_uInt16 >(rPos.Y() - 1);
839 pEditView->SetSelection(ESelection(nRow, nCol - 1, nRow, nCol));
840 GrabFocus();
844 // Makes selection to next <?> symbol
845 void SmEditWindow::SelNextMark()
847 EditEngine *pEditEngine = GetEditEngine();
848 OSL_ENSURE( pEditView, "NULL pointer" );
849 OSL_ENSURE( pEditEngine, "NULL pointer" );
850 if (pEditEngine && pEditView)
852 ESelection eSelection = pEditView->GetSelection();
853 sal_Int32 nPos = eSelection.nEndPos;
854 sal_Int32 nCounts = pEditEngine->GetParagraphCount();
856 while (eSelection.nEndPara < nCounts)
858 OUString aText = pEditEngine->GetText(eSelection.nEndPara);
859 nPos = aText.indexOf("<?>", nPos);
860 if (nPos != -1)
862 pEditView->SetSelection(ESelection(
863 eSelection.nEndPara, nPos, eSelection.nEndPara, nPos + 3));
864 break;
867 nPos = 0;
868 eSelection.nEndPara++;
873 void SmEditWindow::SelPrevMark()
875 EditEngine *pEditEngine = GetEditEngine();
876 OSL_ENSURE( pEditEngine, "NULL pointer" );
877 OSL_ENSURE( pEditView, "NULL pointer" );
878 if (pEditEngine && pEditView)
880 ESelection eSelection = pEditView->GetSelection();
881 sal_Int32 nPos = -1;
882 sal_Int32 nMax = eSelection.nStartPos;
883 OUString aText(pEditEngine->GetText(eSelection.nStartPara));
884 OUString aMark("<?>");
885 sal_Int32 nCounts = pEditEngine->GetParagraphCount();
889 sal_Int32 nMarkIndex = aText.indexOf(aMark);
890 while ((nMarkIndex < nMax) && (nMarkIndex != -1))
892 nPos = nMarkIndex;
893 nMarkIndex = aText.indexOf(aMark, nMarkIndex + 1);
896 if (nPos == -1)
898 eSelection.nStartPara--;
899 aText = pEditEngine->GetText(eSelection.nStartPara);
900 nMax = aText.getLength();
903 while ((eSelection.nStartPara < nCounts) &&
904 (nPos == -1));
906 if (nPos != -1)
908 pEditView->SetSelection(ESelection(
909 eSelection.nStartPara, nPos, eSelection.nStartPara, nPos + 3));
914 bool SmEditWindow::HasMark(const OUString& rText)
915 // returns true iff 'rText' contains a mark
917 return rText.indexOf("<?>") != -1;
920 void SmEditWindow::MouseMove(const MouseEvent &rEvt)
922 if (pEditView)
923 pEditView->MouseMove(rEvt);
926 sal_Int8 SmEditWindow::AcceptDrop( const AcceptDropEvent& /*rEvt*/ )
928 return DND_ACTION_NONE;
931 sal_Int8 SmEditWindow::ExecuteDrop( const ExecuteDropEvent& /*rEvt*/ )
933 return DND_ACTION_NONE;
936 ESelection SmEditWindow::GetSelection() const
938 // pointer may be 0 when reloading a document and the old view
939 // was already destroyed
940 //(OSL_ENSURE( pEditView, "NULL pointer" );
941 ESelection eSel;
942 if (pEditView)
943 eSel = pEditView->GetSelection();
944 return eSel;
947 void SmEditWindow::SetSelection(const ESelection &rSel)
949 OSL_ENSURE( pEditView, "NULL pointer" );
950 if (pEditView)
951 pEditView->SetSelection(rSel);
952 InvalidateSlots();
955 bool SmEditWindow::IsEmpty() const
957 EditEngine *pEditEngine = (const_cast<SmEditWindow *>(this))->GetEditEngine();
958 bool bEmpty = ( pEditEngine && pEditEngine->GetTextLen() == 0 );
959 return bEmpty;
962 bool SmEditWindow::IsSelected() const
964 return pEditView && pEditView->HasSelection();
968 void SmEditWindow::UpdateStatus( bool bSetDocModified )
970 SmModule *pMod = SM_MOD();
971 if (pMod && pMod->GetConfig()->IsAutoRedraw())
972 Flush();
973 if ( bSetDocModified )
974 GetDoc()->SetModified(true);
977 void SmEditWindow::Cut()
979 OSL_ENSURE( pEditView, "EditView missing" );
980 if (pEditView)
982 pEditView->Cut();
983 UpdateStatus(true);
987 void SmEditWindow::Copy()
989 OSL_ENSURE( pEditView, "EditView missing" );
990 if (pEditView)
991 pEditView->Copy();
994 void SmEditWindow::Paste()
996 OSL_ENSURE( pEditView, "EditView missing" );
997 if (pEditView)
999 pEditView->Paste();
1000 UpdateStatus(true);
1004 void SmEditWindow::Delete()
1006 OSL_ENSURE( pEditView, "EditView missing" );
1007 if (pEditView)
1009 pEditView->DeleteSelected();
1010 UpdateStatus(true);
1014 void SmEditWindow::InsertText(const OUString& rText)
1016 OSL_ENSURE( pEditView, "EditView missing" );
1017 if (pEditView)
1019 // Note: Insertion of a space in front of commands is done here and
1020 // in SmEditWindow::InsertCommand.
1021 ESelection aSelection = pEditView->GetSelection();
1022 OUString aCurrentFormula = pEditView->GetEditEngine()->GetText();
1023 sal_Int32 nStartIndex = 0;
1024 sal_Int32 nEndIndex = 0;
1026 // get the start position (when we get a multi line formula)
1027 for (sal_Int32 nParaPos = 0; nParaPos < aSelection.nStartPara; nParaPos++)
1028 nStartIndex = aCurrentFormula.indexOf("\n", nStartIndex) + 1;
1030 nStartIndex += aSelection.nStartPos;
1032 // get the end position (when we get a multi line formula)
1033 for (sal_Int32 nParaPos = 0; nParaPos < aSelection.nEndPara; nParaPos++)
1034 nEndIndex = aCurrentFormula.indexOf("\n", nEndIndex) + 1;
1036 nEndIndex += aSelection.nEndPos;
1038 // TODO: unify this function with the InsertCommand: The do the same thing for different
1039 // callers
1040 OUString string(rText);
1042 // put a space before a new command if not in the beginning of a line
1043 if (aSelection.nStartPos > 0 && aCurrentFormula[nStartIndex - 1] != ' ')
1044 string = " " + string;
1047 fdo#65588 - Elements Dock: Scrollbar moves into input window
1048 This change "solves" the visual problem. But I don't think so
1049 this is the best solution.
1051 pVScrollBar->Hide();
1052 pHScrollBar->Hide();
1053 pEditView->InsertText(string);
1054 AdjustScrollBars();
1055 pVScrollBar->Show();
1056 pHScrollBar->Show();
1058 // Remember start of the selection and move the cursor there afterwards.
1059 aSelection.nEndPara = aSelection.nStartPara;
1060 if (HasMark(string))
1062 aSelection.nEndPos = aSelection.nStartPos;
1063 pEditView->SetSelection(aSelection);
1064 SelNextMark();
1066 else
1067 { // set selection after inserted text
1068 aSelection.nEndPos = aSelection.nStartPos + string.getLength();
1069 aSelection.nStartPos = aSelection.nEndPos;
1070 pEditView->SetSelection(aSelection);
1073 aModifyIdle.Start();
1074 StartCursorMove();
1075 GrabFocus();
1079 void SmEditWindow::Flush()
1081 EditEngine *pEditEngine = GetEditEngine();
1082 if (pEditEngine && pEditEngine->IsModified())
1084 pEditEngine->ClearModifyFlag();
1085 SmViewShell *pViewSh = rCmdBox.GetView();
1086 if (pViewSh)
1088 pViewSh->GetViewFrame()->GetDispatcher()->Execute(
1089 SID_TEXT, SfxCallMode::RECORD,
1090 new SfxStringItem(SID_TEXT, GetText()), 0L);
1093 if (aCursorMoveIdle.IsActive())
1095 aCursorMoveIdle.Stop();
1096 CursorMoveTimerHdl(&aCursorMoveIdle);
1100 void SmEditWindow::DeleteEditView( SmViewShell & /*rView*/ )
1102 if (pEditView)
1104 std::unique_ptr<EditEngine> xEditEngine(pEditView->GetEditEngine());
1105 if (xEditEngine)
1107 xEditEngine->SetStatusEventHdl( Link<>() );
1108 xEditEngine->RemoveView( pEditView.get() );
1110 pEditView.reset();
1114 uno::Reference< XAccessible > SmEditWindow::CreateAccessible()
1116 if (!pAccessible)
1118 pAccessible = new SmEditAccessible( this );
1119 xAccessible = pAccessible;
1120 pAccessible->Init();
1122 return xAccessible;
1125 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */