summaryrefslogtreecommitdiff
path: root/sc
diff options
context:
space:
mode:
authorEike Rathke <erack@redhat.com>2023-04-25 16:44:25 +0200
committerCaolán McNamara <caolanm@redhat.com>2023-05-07 20:50:47 +0200
commitf6a783af88b571ff1f3df9bda31eb0aac66a2c5f (patch)
treeae84c83fe4c59f13068db2c28b7c7626dca65f1a /sc
parentb6c0738f2a1906c2b5a967793e9b065a1b43d75e (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 (cherry picked from commit 82b887c026cb6b0506ebecdcbc8e4b30362ec55b) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151010 Reviewed-by: Caolán McNamara <caolanm@redhat.com>
Diffstat (limited to 'sc')
-rw-r--r--sc/source/ui/app/inputhdl.cxx72
-rw-r--r--sc/source/ui/inc/rfindlst.hxx12
2 files changed, 53 insertions, 31 deletions
diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx
index 75655d807b73..422a9a128508 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.getStr() );
}
+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;
diff --git a/sc/source/ui/inc/rfindlst.hxx b/sc/source/ui/inc/rfindlst.hxx
index 18e13a09b2d3..216264cc2916 100644
--- a/sc/source/ui/inc/rfindlst.hxx
+++ b/sc/source/ui/inc/rfindlst.hxx
@@ -22,19 +22,19 @@
#include <tools/color.hxx>
#include <address.hxx>
#include <tools/solar.h>
+#include <editeng/editdata.hxx>
#include <vector>
struct ScRangeFindData
{
ScRange aRef;
+ ESelection maSel;
ScRefFlags nFlags;
- sal_Int32 nSelStart;
- sal_Int32 nSelEnd;
Color nColor;
- ScRangeFindData( const ScRange& rR, ScRefFlags nF, sal_Int32 nS, sal_Int32 nE ) :
- aRef(rR), nFlags(nF), nSelStart(nS), nSelEnd(nE) {}
+ ScRangeFindData( const ScRange& rR, ScRefFlags nF, const ESelection& rSel ) :
+ aRef(rR), maSel(rSel), nFlags(nF) {}
};
class ScRangeFindList
@@ -47,10 +47,10 @@ class ScRangeFindList
public:
ScRangeFindList(OUString aName);
- sal_uLong Count() const { return maEntries.size(); }
+ size_t Count() const { return maEntries.size(); }
Color Insert( const ScRangeFindData &rNew );
- ScRangeFindData& GetObject( sal_uLong nIndex ) { return maEntries[nIndex]; }
+ ScRangeFindData& GetObject( size_t nIndex ) { return maEntries[nIndex]; }
void SetHidden( bool bSet ) { bHidden = bSet; }