diff options
author | Eike Rathke <erack@redhat.com> | 2023-04-25 16:44:25 +0200 |
---|---|---|
committer | Eike Rathke <erack@redhat.com> | 2023-04-25 20:35:00 +0200 |
commit | 5f6d27711a297d1851dc6bc713fd16c44014cf5c (patch) | |
tree | 9161fc0c4d6396f375f2d856ad00b922151cd9b2 /sc/source/ui/app/inputhdl.cxx | |
parent | a8493ee3d7dac611286a75516f24dd6e451f9718 (diff) |
Resolves: tdf#144547 ScRangeFindList: handle references in multi-line formula
Also fix a color attribution error if when dragging the reference
the new reference string is longer (colored too short) or shorter
(colored too much including the next characters/operator/...) than
the old reference string.
Change-Id: I1b39fd5778d75290a0233f51a4198753fa858f48
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150979
Reviewed-by: Eike Rathke <erack@redhat.com>
Tested-by: Jenkins
Diffstat (limited to 'sc/source/ui/app/inputhdl.cxx')
-rw-r--r-- | sc/source/ui/app/inputhdl.cxx | 72 |
1 files changed, 47 insertions, 25 deletions
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index c0ee11966887..00fc7e429eb4 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -341,6 +341,20 @@ void ScInputHandler::SendReferenceMarks( const SfxViewShell* pViewShell, LOK_CALLBACK_REFERENCE_MARKS, aPayload ); } +static inline void incPos( const sal_Unicode c, sal_Int32& rPos, ESelection& rSel ) +{ + ++rPos; + if (c == '\n') + { + ++rSel.nEndPara; + rSel.nEndPos = 0; + } + else + { + ++rSel.nEndPos; + } +} + void ScInputHandler::InitRangeFinder( const OUString& rFormula ) { DeleteRangeFinder(); @@ -350,7 +364,7 @@ void ScInputHandler::InitRangeFinder( const OUString& rFormula ) ScDocument& rDoc = pDocSh->GetDocument(); const sal_Unicode cSheetSep = rDoc.GetSheetSeparator(); - OUString aDelimiters = ScEditUtil::ModifyDelimiters(" !~\""); + OUString aDelimiters = ScEditUtil::ModifyDelimiters(" !~\"\t\n"); // delimiters (in addition to ScEditUtil): only characters that are // allowed in formulas next to references and the quotation mark (so // string constants can be skipped) @@ -366,6 +380,7 @@ void ScInputHandler::InitRangeFinder( const OUString& rFormula ) sal_Int32 nLen = rFormula.getLength(); sal_Int32 nPos = 0; sal_Int32 nStart = 0; + ESelection aSel; sal_uInt16 nCount = 0; ScRange aRange; while ( nPos < nLen && nCount < RANGEFIND_MAX ) @@ -375,14 +390,16 @@ void ScInputHandler::InitRangeFinder( const OUString& rFormula ) { if ( pChar[nPos] == '"' ) // String { - ++nPos; + incPos( pChar[nPos], nPos, aSel); while (nPos<nLen && pChar[nPos] != '"') // Skip until end - ++nPos; + incPos( pChar[nPos], nPos, aSel); } - ++nPos; // Separator or closing quote + incPos( pChar[nPos], nPos, aSel); // Separator or closing quote } - // text between separators + // Text between separators. We only consider within one line/paragraph. + aSel.nStartPara = aSel.nEndPara; + aSel.nStartPos = aSel.nEndPos; nStart = nPos; handle_r1c1: { @@ -400,7 +417,7 @@ handle_r1c1: if (ScGlobal::UnicodeStrChr(aDelimiters.getStr(), pChar[nPos])) break; } - ++nPos; + incPos( pChar[nPos], nPos, aSel); } } @@ -411,7 +428,7 @@ handle_r1c1: '-' == pChar[nPos] && '[' == pChar[nPos-1] && formula::FormulaGrammar::CONV_XL_R1C1 == rDoc.GetAddressConvention() ) { - nPos++; + incPos( pChar[nPos], nPos, aSel); goto handle_r1c1; } @@ -443,9 +460,8 @@ handle_r1c1: pRangeFindList.reset(new ScRangeFindList( pDocSh->GetTitle() )); } - Color nColor = pRangeFindList->Insert( ScRangeFindData( aRange, nFlags, nStart, nPos ) ); + Color nColor = pRangeFindList->Insert( ScRangeFindData( aRange, nFlags, aSel)); - ESelection aSel( 0, nStart, 0, nPos ); SfxItemSet aSet( mpEditEngine->GetEmptyItemSet() ); aSet.Put( SvxColorItem( nColor, EE_CHAR_COLOR ) ); mpEditEngine->QuickSetAttribs( aSet, aSel ); @@ -620,8 +636,9 @@ static void lcl_Replace( EditView* pView, const OUString& rNewStr, const ESelect // To do that we need to cancel the selection from above (before QuickInsertText) pView->InsertText( OUString() ); - sal_Int32 nLen = pEngine->GetTextLen(0); - ESelection aSel( 0, nLen, 0, nLen ); + const sal_Int32 nPara = pEngine->GetParagraphCount() - 1; + const sal_Int32 nLen = pEngine->GetTextLen(nPara); + ESelection aSel( nPara, nLen, nPara, nLen ); pView->SetSelection( aSel ); // Set cursor to the end } @@ -631,8 +648,6 @@ void ScInputHandler::UpdateRange( sal_uInt16 nIndex, const ScRange& rNew ) if ( pDocView && pRangeFindList && nIndex < pRangeFindList->Count() ) { ScRangeFindData& rData = pRangeFindList->GetObject( nIndex ); - sal_Int32 nOldStart = rData.nSelStart; - sal_Int32 nOldEnd = rData.nSelEnd; Color nNewColor = pRangeFindList->FindColor( rNew, nIndex ); ScRange aJustified = rNew; @@ -640,32 +655,39 @@ void ScInputHandler::UpdateRange( sal_uInt16 nIndex, const ScRange& rNew ) ScDocument& rDoc = pDocView->GetViewData().GetDocument(); const ScAddress::Details aAddrDetails( rDoc, aCursorPos ); OUString aNewStr(aJustified.Format(rDoc, rData.nFlags, aAddrDetails)); - ESelection aOldSel( 0, nOldStart, 0, nOldEnd ); SfxItemSet aSet( mpEditEngine->GetEmptyItemSet() ); DataChanging(); - lcl_Replace( pTopView, aNewStr, aOldSel ); - lcl_Replace( pTableView, aNewStr, aOldSel ); + lcl_Replace( pTopView, aNewStr, rData.maSel ); + lcl_Replace( pTableView, aNewStr, rData.maSel ); + + // We are within one paragraph. + const sal_Int32 nDiff = aNewStr.getLength() - (rData.maSel.nEndPos - rData.maSel.nStartPos); + rData.maSel.nEndPos += nDiff; + aSet.Put( SvxColorItem( nNewColor, EE_CHAR_COLOR ) ); - mpEditEngine->QuickSetAttribs( aSet, aOldSel ); + mpEditEngine->QuickSetAttribs( aSet, rData.maSel ); bInRangeUpdate = true; DataChanged(); bInRangeUpdate = false; - tools::Long nDiff = aNewStr.getLength() - static_cast<tools::Long>(nOldEnd-nOldStart); - rData.aRef = rNew; - rData.nSelEnd = rData.nSelEnd + nDiff; rData.nColor = nNewColor; - sal_uInt16 nCount = static_cast<sal_uInt16>(pRangeFindList->Count()); - for (sal_uInt16 i=nIndex+1; i<nCount; i++) + if (nDiff) { - ScRangeFindData& rNext = pRangeFindList->GetObject( i ); - rNext.nSelStart = rNext.nSelStart + nDiff; - rNext.nSelEnd = rNext.nSelEnd + nDiff; + const size_t nCount = pRangeFindList->Count(); + for (size_t i = nIndex + 1; i < nCount; ++i) + { + ScRangeFindData& rNext = pRangeFindList->GetObject( i ); + if (rNext.maSel.nStartPara != rData.maSel.nStartPara) + break; + + rNext.maSel.nStartPos += nDiff; + rNext.maSel.nEndPos += nDiff; + } } EditView* pActiveView = pTopView ? pTopView : pTableView; |