sc/source/ui/app/inputhdl.cxx |   72 +++++++++++++++++++++++++++---------------
 sc/source/ui/inc/rfindlst.hxx |   12 +++----
 2 files changed, 53 insertions(+), 31 deletions(-)

New commits:
commit f6a783af88b571ff1f3df9bda31eb0aac66a2c5f
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Tue Apr 25 16:44:25 2023 +0200
Commit:     Caolán McNamara <caol...@redhat.com>
CommitDate: Sun May 7 20:50:47 2023 +0200

    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 <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 82b887c026cb6b0506ebecdcbc8e4b30362ec55b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151010
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

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; }
 

Reply via email to