diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx index 4096e0e18bf8..f243d6d8feb6 100644 --- a/editeng/source/editeng/editview.cxx +++ b/editeng/source/editeng/editview.cxx @@ -1394,6 +1394,53 @@ const SvxFieldData* EditView::GetFieldAtCursor() const return pFieldItem ? pFieldItem->GetField() : nullptr; } +sal_Int32 EditView::countFieldsOffsetSum(sal_Int32 nPara, sal_Int32 nPos, bool bCanOverflow) const +{ + if (!pImpEditView || !pImpEditView->pEditEngine) + return 0; + + int nOffset = 0; + + for (int nCurrentPara = 0; nCurrentPara <= nPara; nCurrentPara++) + { + int nFields = pImpEditView->pEditEngine->GetFieldCount( nCurrentPara ); + for (int nField = 0; nField < nFields; nField++) + { + EFieldInfo aFieldInfo + = pImpEditView->pEditEngine->GetFieldInfo( nCurrentPara, nField ); + + bool bLastPara = nCurrentPara == nPara; + sal_Int32 nFieldPos = aFieldInfo.aPosition.nIndex; + + if (bLastPara && nFieldPos >= nPos) + break; + + sal_Int32 nFieldLen = aFieldInfo.aCurrentText.getLength(); + + // position in the middle of a field + if (!bCanOverflow && bLastPara && nFieldPos + nFieldLen > nPos) + nFieldLen = nPos - nFieldPos; + + nOffset += nFieldLen - 1; + } + } + + return nOffset; +} + +sal_Int32 EditView::GetPosNoField(sal_Int32 nPara, sal_Int32 nPos) const +{ + sal_Int32 nOffset = countFieldsOffsetSum(nPara, nPos, false); + assert(nPos >= nOffset); + return nPos - nOffset; +} + +sal_Int32 EditView::GetPosWithField(sal_Int32 nPara, sal_Int32 nPos) const +{ + sal_Int32 nOffset = countFieldsOffsetSum(nPara, nPos, true); + return nPos + nOffset; +} + void EditView::SetInvalidateMore( sal_uInt16 nPixel ) { pImpEditView->SetInvalidateMore( nPixel ); diff --git a/include/editeng/editview.hxx b/include/editeng/editview.hxx index 17ed1bb4e7ac..73d4c23f49a9 100644 --- a/include/editeng/editview.hxx +++ b/include/editeng/editview.hxx @@ -160,6 +160,10 @@ private: EditView( const EditView& ) = delete; EditView& operator=( const EditView& ) = delete; + // counts how many characters take unfolded fields + // bCanOverflow - count field length without trim to the selected pos + sal_Int32 countFieldsOffsetSum(sal_Int32 nPara, sal_Int32 nPo, bool bCanOverflow) const; + public: EditView( EditEngine* pEng, vcl::Window* pWindow ); ~EditView(); @@ -316,6 +320,10 @@ public: /// Select and return the field at the current cursor position const SvxFieldData* GetFieldAtCursor() const; void SelectFieldAtCursor(); + /// Converts position in paragraph to logical position without unfolding fields + sal_Int32 GetPosNoField(sal_Int32 nPara, sal_Int32 nPos) const; + /// Converts logical position in paragraph to position with unfolded fields + sal_Int32 GetPosWithField(sal_Int32 nPara, sal_Int32 nPos) const; void SetInvalidateMore( sal_uInt16 nPixel ); sal_uInt16 GetInvalidateMore() const; diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 75655d807b73..f80b6c1b49a8 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -1781,13 +1781,23 @@ void ScInputHandler::LOKPasteFunctionData(const OUString& rFunctionName) } } -void ScInputHandler::LOKSendFormulabarUpdate(const SfxViewShell* pActiveViewSh, +void ScInputHandler::LOKSendFormulabarUpdate(EditView* pActiveView, + const SfxViewShell* pActiveViewSh, const OUString& rText, const ESelection& rSelection) { - OUString aSelection = - OUString::number(rSelection.nStartPos) + ";" + OUString::number(rSelection.nEndPos) + ";" + - OUString::number(rSelection.nStartPara) + ";" + OUString::number(rSelection.nEndPara); + OUString aSelection; + if (pActiveView) + { + aSelection = OUString::number(pActiveView->GetPosWithField(0, rSelection.nStartPos)) + ";" + + OUString::number(pActiveView->GetPosWithField(0, rSelection.nEndPos)) + ";" + + OUString::number(rSelection.nStartPara) + ";" + OUString::number(rSelection.nEndPara); + } + else + { + aSelection = OUString::number(rSelection.nStartPos) + ";" + OUString::number(rSelection.nEndPos) + ";" + + OUString::number(rSelection.nStartPara) + ";" + OUString::number(rSelection.nEndPara); + } std::unique_ptr pData = std::make_unique(); (*pData)["action_type"] = "setText"; @@ -2775,7 +2785,7 @@ void ScInputHandler::DataChanged( bool bFromTopNotify, bool bSetModified ) if (pActiveView) aSel = pActiveView->GetSelection(); - ScInputHandler::LOKSendFormulabarUpdate(pActiveViewSh, + ScInputHandler::LOKSendFormulabarUpdate(pActiveView, pActiveViewSh, ScEditUtil::GetMultilineString(*mpEditEngine), aSel); } @@ -4248,7 +4258,7 @@ void ScInputHandler::NotifyChange( const ScInputHdlState* pState, if (aSel.nEndPara == EE_PARA_NOT_FOUND) aSel.nEndPara = 0; - ScInputHandler::LOKSendFormulabarUpdate(pActiveViewSh, aString, aSel); + ScInputHandler::LOKSendFormulabarUpdate(pActiveView, pActiveViewSh, aString, aSel); // TODO: deprecated? pActiveViewSh->libreOfficeKitViewCallback(LOK_CALLBACK_CELL_FORMULA, aString.toUtf8().getStr()); } @@ -4412,7 +4422,7 @@ void ScInputHandler::InputSelection( const EditView* pView ) { EditView* pActiveView = pTopView ? pTopView : pTableView; ESelection aSel = pActiveView ? pActiveView->GetSelection() : ESelection(); - ScInputHandler::LOKSendFormulabarUpdate(pActiveViewSh, GetEditString(), aSel); + ScInputHandler::LOKSendFormulabarUpdate(pActiveView, pActiveViewSh, GetEditString(), aSel); } } diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index a9b5a54367b9..ed82c9d7a0a3 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -1149,7 +1149,7 @@ ScTextWndGroup::ScTextWndGroup(ScInputBarGroup& rParent, ScTabViewShell* pViewSh { mxScrollWin->connect_vadjustment_changed(LINK(this, ScTextWndGroup, Impl_ScrollHdl)); if (comphelper::LibreOfficeKit::isActive()) - ScInputHandler::LOKSendFormulabarUpdate(SfxViewShell::Current(), "", ESelection()); + ScInputHandler::LOKSendFormulabarUpdate(nullptr, SfxViewShell::Current(), "", ESelection()); } Point ScTextWndGroup::GetCursorScreenPixelPos(bool bBelow) @@ -1816,8 +1816,10 @@ bool ScTextWnd::Command( const CommandEvent& rCEvt ) { nParaStart = pParaPoint ? pParaPoint->X() : 0; nParaEnd = pParaPoint ? pParaPoint->Y() : 0; - nPosStart = aSelectionStartEnd.X(); - nPosEnd = aSelectionStartEnd.Y(); + nPosStart = m_xEditView->GetPosNoField(nParaStart, aSelectionStartEnd.X()); + nPosEnd = m_xEditView->GetPosNoField(nParaEnd, aSelectionStartEnd.Y()); + + } m_xEditView->SetSelection(ESelection(nParaStart, nPosStart, nParaEnd, nPosEnd)); @@ -2059,7 +2061,7 @@ void ScTextWnd::SetTextString( const OUString& rNewString ) if (comphelper::LibreOfficeKit::isActive()) { ESelection aSel = m_xEditView ? m_xEditView->GetSelection() : ESelection(); - ScInputHandler::LOKSendFormulabarUpdate(SfxViewShell::Current(), rNewString, aSel); + ScInputHandler::LOKSendFormulabarUpdate(m_xEditView.get(), SfxViewShell::Current(), rNewString, aSel); } SetScrollBarRange(); diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx index 1506a0c2a2b3..90a562f6c11f 100644 --- a/sc/source/ui/inc/inputhdl.hxx +++ b/sc/source/ui/inc/inputhdl.hxx @@ -295,7 +295,7 @@ public: tools::Long nTab, const Color& rColor ); void LOKPasteFunctionData(const OUString& rFunctionName); - static void LOKSendFormulabarUpdate(const SfxViewShell* pActiveViewSh, + static void LOKSendFormulabarUpdate(EditView* pEditView, const SfxViewShell* pActiveViewSh, const OUString& rText, const ESelection& rSelection); };