include/svl/zformat.hxx               |    4 +
 sc/inc/listenercalls.hxx              |    6 +-
 sc/source/core/data/documen4.cxx      |   23 +++------
 sc/source/core/data/table2.cxx        |   18 +++++--
 sc/source/ui/app/inputhdl.cxx         |   20 ++++++--
 sc/source/ui/inc/inputhdl.hxx         |    2 
 sc/source/ui/unoobj/cellsuno.cxx      |    4 +
 sc/source/ui/unoobj/listenercalls.cxx |    2 
 sc/source/ui/vba/vbarange.cxx         |   81 +++++++++++++++++++++-------------
 sc/source/ui/vba/vbarange.hxx         |    3 +
 svl/source/numbers/zforlist.cxx       |   17 +++----
 svl/source/numbers/zformat.cxx        |   28 +++++++++++
 xmloff/source/style/xmlnumfe.cxx      |   31 +++++++++++++
 xmloff/source/style/xmlnumfi.cxx      |   24 +++++-----
 14 files changed, 186 insertions(+), 77 deletions(-)

New commits:
commit c649ad711ec48d08b0761f420f4584768c82eb74
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Tue Jun 21 09:49:31 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:25 2022 +0200

    Resolves: tdf#149589 No "+ or - may start formula" when editing content
    
    If it was a formula already it would start with = anyway.
    
    Change-Id: Ib3c0ebcaf99231d387f1aace8e1a5642061de3a0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136208
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 909cdd552199d35f7c10be0a8be370158aea0815)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136173
    Tested-by: Eike Rathke <er...@redhat.com>
    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 d1a2fea3d482..e2343e052cfe 100644
--- a/sc/source/ui/app/inputhdl.cxx
+++ b/sc/source/ui/app/inputhdl.cxx
@@ -831,6 +831,7 @@ ScInputHandler::ScInputHandler()
         bLastIsSymbol( false ),
         mbDocumentDisposing(false),
         mbPartialPrefix(false),
+        mbEditingExistingContent(false),
         nValidation( 0 ),
         eAttrAdjust( SvxCellHorJustify::Standard ),
         aScaleX( 1,1 ),
@@ -1769,6 +1770,9 @@ void ScInputHandler::LOKPasteFunctionData(const OUString& 
rFunctionName)
     if (pEditEngine)
     {
         aFormula = pEditEngine->GetText(0);
+        /* TODO: LOK: are you sure you want '+' and '-' let start formulas with
+         * function names? That was meant for "data typist" numeric keyboard
+         * input. */
         bEdit = aFormula.getLength() > 1 && (aFormula[0] == '=' || aFormula[0] 
== '+' || aFormula[0] == '-');
     }
 
@@ -2575,6 +2579,7 @@ bool ScInputHandler::StartTable( sal_Unicode cTyped, bool 
bFromCommand, bool bIn
             }
             else
                 aStr = GetEditText(mpEditEngine.get());
+            mbEditingExistingContent = !aStr.isEmpty();
 
             if (aStr.startsWith("{=") && aStr.endsWith("}") )  // Matrix 
formula?
             {
@@ -2589,8 +2594,7 @@ bool ScInputHandler::StartTable( sal_Unicode cTyped, bool 
bFromCommand, bool bIn
             if ( bAutoComplete )
                 GetColData();
 
-            if ( !aStr.isEmpty() && ( aStr[0] == '=' || aStr[0] == '+' || 
aStr[0] == '-' ) &&
-                 !cTyped && !bCreatingFuncView )
+            if (!cTyped && !bCreatingFuncView && StartsLikeFormula(aStr))
                 InitRangeFinder(aStr); // Formula is being edited -> 
RangeFinder
 
             bNewTable = true; // -> PostEditView Call
@@ -2792,6 +2796,13 @@ void ScInputHandler::DataChanged( bool bFromTopNotify, 
bool bSetModified )
     bInOwnChange = false;
 }
 
+bool ScInputHandler::StartsLikeFormula( std::u16string_view rStr ) const
+{
+    // For new input '+' and '-' may start the dreaded "lazy data typist"
+    // formula input, editing existing formula content can only start with '='.
+    return !rStr.empty() && (rStr[0] == '=' || (!mbEditingExistingContent && 
(rStr[0] == '+' || rStr[0] == '-')));
+}
+
 void ScInputHandler::UpdateFormulaMode()
 {
     SfxApplication* pSfxApp = SfxGetpApp();
@@ -2800,8 +2811,7 @@ void ScInputHandler::UpdateFormulaMode()
     if (bIsFormula)
     {
         const OUString& rText = mpEditEngine->GetText(0);
-        bIsFormula = !rText.isEmpty() &&
-            (rText[0] == '=' || rText[0] == '+' || rText[0] == '-');
+        bIsFormula = StartsLikeFormula(rText);
     }
 
     if ( bIsFormula )
@@ -3407,6 +3417,7 @@ void ScInputHandler::EnterHandler( ScEnterMode 
nBlockMode, bool bBeforeSavingInL
     nFormSelStart = nFormSelEnd = 0;
     aFormText.clear();
 
+    mbEditingExistingContent = false;
     bInOwnChange = false;
     bInEnterHandler = false;
 }
@@ -3419,6 +3430,7 @@ void ScInputHandler::CancelHandler()
 
     bModified = false;
     mbPartialPrefix = false;
+    mbEditingExistingContent = false;
 
     // Don't rely on ShowRefFrame switching the active view synchronously
     // execute the function directly on the correct view's bindings instead
diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx
index 1450f26c8176..56ed3bb95b1f 100644
--- a/sc/source/ui/inc/inputhdl.hxx
+++ b/sc/source/ui/inc/inputhdl.hxx
@@ -105,6 +105,7 @@ private:
     bool                    mbDocumentDisposing:1;
     /// To indicate if there is a partial prefix completion.
     bool                    mbPartialPrefix:1;
+    bool                    mbEditingExistingContent:1;
 
     sal_uLong                   nValidation;
     SvxCellHorJustify       eAttrAdjust;
@@ -146,6 +147,7 @@ private:
     bool            StartTable( sal_Unicode cTyped, bool bFromCommand, bool 
bInputActivated,
                                 ScEditEngineDefaulter* pTopEngine );
     void            RemoveSelection();
+    bool            StartsLikeFormula( std::u16string_view rStr ) const;
     void            UpdateFormulaMode();
     static void     InvalidateAttribs();
     void            ImplCreateEditEngine();
commit 50c0e041c06fccb84a84be6d2f457ad0aa0a3c6f
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Mon Jun 20 17:13:53 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:25 2022 +0200

    Resolves: tdf#147265 Return correct default if currency format is duplicate
    
    For the default currency format
    SvNumberFormatter::GetCurrencyFormatStrings() returned always the
    last added position, regardless whether that format was added or
    not, which it isn't if the format code is a duplicate. Let
    addToCurrencyFormatsList() return the position of the existing
    format if the duplicate was rejected and use that for default.
    
    Change-Id: I148d7379de75cae402b063f7b2f92947e345176f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136187
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 36cf12d449c892e6bbacb7da5f4b008f7762232b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136166
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/svl/source/numbers/zforlist.cxx b/svl/source/numbers/zforlist.cxx
index fbd05a481df9..6a9934fdbed1 100644
--- a/svl/source/numbers/zforlist.cxx
+++ b/svl/source/numbers/zforlist.cxx
@@ -4285,12 +4285,16 @@ void SvNumberFormatter::ImpInitCurrencyTable()
 }
 
 
-static void addToCurrencyFormatsList( NfWSStringsDtor& rStrArr, const 
OUString& rFormat )
+static std::ptrdiff_t addToCurrencyFormatsList( NfWSStringsDtor& rStrArr, 
const OUString& rFormat )
 {
     // Prevent duplicates even over subsequent calls of
     // GetCurrencyFormatStrings() with the same vector.
-    if (std::find( rStrArr.begin(), rStrArr.end(), rFormat) == rStrArr.end())
-        rStrArr.push_back( rFormat);
+    NfWSStringsDtor::const_iterator it( std::find( rStrArr.begin(), 
rStrArr.end(), rFormat));
+    if (it != rStrArr.end())
+        return it - rStrArr.begin();
+
+    rStrArr.push_back( rFormat);
+    return rStrArr.size() - 1;
 }
 
 
@@ -4319,9 +4323,7 @@ sal_uInt16 SvNumberFormatter::GetCurrencyFormatStrings( 
NfWSStringsDtor& rStrArr
                          + ";"
                          + aRed
                          + aNegativeBank;
-        addToCurrencyFormatsList( rStrArr, format2);
-
-        nDefault = rStrArr.size() - 1;
+        nDefault = addToCurrencyFormatsList( rStrArr, format2);
     }
     else
     {
@@ -4374,8 +4376,7 @@ sal_uInt16 SvNumberFormatter::GetCurrencyFormatStrings( 
NfWSStringsDtor& rStrArr
         {
             addToCurrencyFormatsList( rStrArr, format3);
         }
-        addToCurrencyFormatsList( rStrArr, format4);
-        nDefault = rStrArr.size() - 1;
+        nDefault = addToCurrencyFormatsList( rStrArr, format4);
         if (rCurr.GetDigits())
         {
             addToCurrencyFormatsList( rStrArr, format5);
commit 48de5010d88454e886aa8b280ae51a6ee884b870
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Thu Jun 16 21:44:40 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:25 2022 +0200

    Resolves: tdf#147822 ScUnoListenerEntry container must be std::list
    
    ... instead of std::vector to not get invalidated iterators when
    the container is resized.
    
    Regression from
    
        commit f8defe59ff75df2b516ee407f1dac22b0ac72a19
        CommitDate: Wed Sep 6 22:45:10 2017 +0200
    
            Replace some lists by vectors in unoobj (sc)
    
    which was bad for this case.
    
    Change-Id: I8d3a001242865cadc82b359a3198906d26373a41
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136007
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 7a0a0e23b7e81c1ee0601824a4ee990a2178f98b)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/136023
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sc/inc/listenercalls.hxx b/sc/inc/listenercalls.hxx
index ff835a048b1a..acb009937fa1 100644
--- a/sc/inc/listenercalls.hxx
+++ b/sc/inc/listenercalls.hxx
@@ -19,7 +19,7 @@
 
 #pragma once
 
-#include <vector>
+#include <list>
 #include <com/sun/star/uno/Reference.hxx>
 #include <com/sun/star/lang/EventObject.hpp>
 
@@ -48,7 +48,9 @@ struct ScUnoListenerEntry
 class ScUnoListenerCalls
 {
 private:
-    ::std::vector<ScUnoListenerEntry> aEntries;
+    // Must be list, not vector, to not invalidate iterators, see
+    // ExecuteAndClear() implementation.
+    ::std::list<ScUnoListenerEntry> aEntries;
 
 public:
                 ScUnoListenerCalls();
diff --git a/sc/source/ui/unoobj/listenercalls.cxx 
b/sc/source/ui/unoobj/listenercalls.cxx
index 2d9a23083ca8..7ff7c7df0956 100644
--- a/sc/source/ui/unoobj/listenercalls.cxx
+++ b/sc/source/ui/unoobj/listenercalls.cxx
@@ -44,7 +44,7 @@ void ScUnoListenerCalls::ExecuteAndClear()
     //  During each modified() call, Add may be called again.
     //  These new calls are executed here, too.
 
-    std::vector<ScUnoListenerEntry>::iterator aItr(aEntries.begin());
+    std::list<ScUnoListenerEntry>::iterator aItr(aEntries.begin());
     while (aItr != aEntries.end())
     {
         ScUnoListenerEntry aEntry = *aItr;
commit 8905d516cfecb2a3d6a4302fee162b9be6e5049f
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Tue Jun 14 13:55:09 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:25 2022 +0200

    Related: tdf#149325 Fix yet another VbaRange empty ScRangeList access
    
    Change-Id: If2c44795ab794482b841138bdd55f37c4d30b592
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135824
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 9470c5531dc928d438a6a7f4d47f2d82f2296cc1)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135874
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx
index ca77bae6c093..6ee791bf7212 100644
--- a/sc/source/ui/unoobj/cellsuno.cxx
+++ b/sc/source/ui/unoobj/cellsuno.cxx
@@ -6717,7 +6717,9 @@ uno::Reference<sheet::XSheetCellCursor> SAL_CALL 
ScTableSheetObj::createCursorBy
         if (pRangesImp)
         {
             const ScRangeList& rRanges = pRangesImp->GetRangeList();
-            OSL_ENSURE( rRanges.size() == 1, "Range? Ranges?" );
+            SAL_WARN_IF( rRanges.size() != 1, "sc", 
"ScTableSheetObj::createCursorByRange: Range? Ranges?");
+            if (rRanges.empty())
+                return nullptr;
             return new ScCellCursorObj( pDocSh, rRanges[ 0 ] );
         }
     }
diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index eaba743db01b..92c281cfb8ac 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -1285,9 +1285,12 @@ uno::Reference< sheet::XSheetCellRange > 
lclExpandToMerged( const uno::Reference
     {
         aOldAddress = aNewAddress;
         uno::Reference< sheet::XSheetCellCursor > xCursor( 
xSheet->createCursorByRange( xNewCellRange ), uno::UNO_SET_THROW );
-        xCursor->collapseToMergedArea();
-        xNewCellRange.set( xCursor, uno::UNO_QUERY_THROW );
-        aNewAddress = lclGetRangeAddress( xNewCellRange );
+        if (xCursor.is())
+        {
+            xCursor->collapseToMergedArea();
+            xNewCellRange.set( xCursor, uno::UNO_QUERY_THROW );
+            aNewAddress = lclGetRangeAddress( xNewCellRange );
+        }
     }
     while( bRecursive && (aOldAddress != aNewAddress) );
     return xNewCellRange;
commit 84e51f196567b358f0889c9052a8a2b1615541c3
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Mon Jun 13 17:00:43 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:25 2022 +0200

    tdf#149531 tdf#149325 Eliminate unconditional ScRangeList::front() access
    
     This is a combination of 2 commits.
    
    Resolves: tdf#149531 Use initial sheet range for VBA Columns and Rows
    
    ... if the ScTableSheetObj's ScRangeList is empty. It might even
    be that was never intended to be used and worked only by accident
    in the past (pre 6.0), but it's somewhat unclear. It may even get
    in the way in case it exists and the (first) range was modified,
    e.g. shrunk by a Delete, as the resulting column or row object
    could be different from the initial sheet range.
    
    xChange-Id: Ib9911df1b23802054a5bb0621bb7f5559ef3f39b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135732
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 3ad12672e924f7aef394119f9fe5f0b06a900b9e)
    
    Related: tdf#149325 Eliminate all unconditional ScRangeList::front() access
    
    ... to prevent crashes, and where possible substitute a missing
    element with the original sheet object range.
    
    xChange-Id: I245844e89fa3eb7d6ec07e279bdd23022fd77958
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135773
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit d6331fc7abe545ff0a369c41ab3f55b8f44a2cc1)
    
    Change-Id: Ib9911df1b23802054a5bb0621bb7f5559ef3f39b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135739
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx
index 91f3dc76f72c..eaba743db01b 100644
--- a/sc/source/ui/vba/vbarange.cxx
+++ b/sc/source/ui/vba/vbarange.cxx
@@ -871,15 +871,18 @@ protected:
                 ScCellRangesBase* pUnoRangesBase = dynamic_cast< 
ScCellRangesBase* >( xIf.get() );
                 if ( pUnoRangesBase )
                 {
-                    ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
-                    ScCompiler aCompiler( m_rDoc, aCellRanges.front().aStart, 
m_eGrammar );
-                    // compile the string in the format passed in
-                    std::unique_ptr<ScTokenArray> 
pArray(aCompiler.CompileString(sFormula));
-                    // convert to API grammar
-                    aCompiler.SetGrammar( formula::FormulaGrammar::GRAM_API );
-                    OUString sConverted;
-                    aCompiler.CreateStringFromTokenArray(sConverted);
-                    sFormula = EQUALS + sConverted;
+                    const ScRangeList& rCellRanges = 
pUnoRangesBase->GetRangeList();
+                    if (!rCellRanges.empty())
+                    {
+                        ScCompiler aCompiler( m_rDoc, 
rCellRanges.front().aStart, m_eGrammar );
+                        // compile the string in the format passed in
+                        std::unique_ptr<ScTokenArray> 
pArray(aCompiler.CompileString(sFormula));
+                        // convert to API grammar
+                        aCompiler.SetGrammar( 
formula::FormulaGrammar::GRAM_API );
+                        OUString sConverted;
+                        aCompiler.CreateStringFromTokenArray(sConverted);
+                        sFormula = EQUALS + sConverted;
+                    }
                 }
             }
 
@@ -917,16 +920,19 @@ public:
             {
                 OUString sVal;
                 aValue >>= sVal;
-                ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
-                // Compile string from API grammar.
-                ScCompiler aCompiler( m_rDoc, aCellRanges.front().aStart, 
formula::FormulaGrammar::GRAM_API );
-                std::unique_ptr<ScTokenArray> 
pArray(aCompiler.CompileString(sVal));
-                // Convert to desired grammar.
-                aCompiler.SetGrammar( m_eGrammar );
-                OUString sConverted;
-                aCompiler.CreateStringFromTokenArray(sConverted);
-                sVal = EQUALS + sConverted;
-                aValue <<= sVal;
+                const ScRangeList& rCellRanges = 
pUnoRangesBase->GetRangeList();
+                if (!rCellRanges.empty())
+                {
+                    // Compile string from API grammar.
+                    ScCompiler aCompiler( m_rDoc, rCellRanges.front().aStart, 
formula::FormulaGrammar::GRAM_API );
+                    std::unique_ptr<ScTokenArray> 
pArray(aCompiler.CompileString(sVal));
+                    // Convert to desired grammar.
+                    aCompiler.SetGrammar( m_eGrammar );
+                    OUString sConverted;
+                    aCompiler.CreateStringFromTokenArray(sConverted);
+                    sVal = EQUALS + sConverted;
+                    aValue <<= sVal;
+                }
             }
         }
 
@@ -1920,7 +1926,8 @@ ScVbaRange::Offset( const ::uno::Any &nRowOff, const 
uno::Any &nColOff )
         return new ScVbaRange( mxParent, mxContext, xRanges );
     }
     // normal range
-    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( 
pUnoRangesBase->GetDocShell(), aCellRanges.front() ) );
+    const ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( aCellRanges));
+    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( 
pUnoRangesBase->GetDocShell(), aRange));
     return new ScVbaRange( mxParent, mxContext, xRange  );
 }
 
@@ -2371,17 +2378,28 @@ ScVbaRange::Activate()
 
 }
 
+ScRange ScVbaRange::obtainRangeEvenIfRangeListIsEmpty( const ScRangeList& 
rCellRanges ) const
+{
+    // XXX It may be that using the current range list was never correct, but
+    // always the initial sheet range would be instead, history is unclear.
+
+    if (!rCellRanges.empty())
+        return rCellRanges.front();
+
+    table::CellRangeAddress aRA( lclGetRangeAddress( mxRange ));
+    return ScRange( aRA.StartColumn, aRA.StartRow, aRA.Sheet, aRA.EndColumn, 
aRA.EndRow, aRA.Sheet);
+}
+
 uno::Reference< excel::XRange >
 ScVbaRange::Rows(const uno::Any& aIndex )
 {
     if ( aIndex.hasValue() )
     {
-        sal_Int32 nValue = 0;
         ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
-        ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
-        OUString sAddress;
+        ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( 
pUnoRangesBase->GetRangeList()));
 
-        ScRange aRange = aCellRanges.front();
+        sal_Int32 nValue = 0;
+        OUString sAddress;
         if( aIndex >>= nValue )
         {
             aRange.aStart.SetRow( aRange.aStart.Row() + --nValue );
@@ -2417,9 +2435,8 @@ uno::Reference< excel::XRange >
 ScVbaRange::Columns(const uno::Any& aIndex )
 {
     ScCellRangesBase* pUnoRangesBase = getCellRangesBase();
-    ScRangeList aCellRanges = pUnoRangesBase->GetRangeList();
+    ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( 
pUnoRangesBase->GetRangeList()));
 
-    ScRange aRange = aCellRanges.front();
     if ( aIndex.hasValue() )
     {
         OUString sAddress;
@@ -2933,7 +2950,8 @@ ScVbaRange::getEntireColumnOrRow( bool bColumn )
 
         return new ScVbaRange( mxParent, mxContext, xRanges, !bColumn, bColumn 
);
     }
-    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( 
pUnoRangesBase->GetDocShell(), aCellRanges.front() ) );
+    const ScRange aRange( obtainRangeEvenIfRangeListIsEmpty( aCellRanges));
+    uno::Reference< table::XCellRange > xRange( new ScCellRangeObj( 
pUnoRangesBase->GetDocShell(), aRange));
     return new ScVbaRange( mxParent, mxContext, xRange, !bColumn, bColumn  );
 }
 
diff --git a/sc/source/ui/vba/vbarange.hxx b/sc/source/ui/vba/vbarange.hxx
index 2e9b71746879..cdeab983fa6d 100644
--- a/sc/source/ui/vba/vbarange.hxx
+++ b/sc/source/ui/vba/vbarange.hxx
@@ -119,6 +119,9 @@ class ScVbaRange : public ScVbaRange_BASE
     /** Fires a Worksheet_Change event for this range or range list. */
     void fireChangeEvent();
 
+    /// @throws css::uno::RuntimeException
+    ScRange obtainRangeEvenIfRangeListIsEmpty( const ScRangeList& rCellRanges 
) const;
+
 protected:
     virtual ScCellRangesBase* getCellRangesBase() override;
     /// @throws css::uno::RuntimeException
commit cb49f6a3a10b16828384fc0b3798f8d923e25d29
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Fri Jun 10 12:34:00 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:24 2022 +0200

    Resolves: tdf#149484 Handle <number:boolean-style> with <number:text>
    
    Backport as the current handling when writing such format (even if it
    doesn't display the text literals) is utterly broken and results in
    
        <number:boolean-style style:name="N111">
          <number:text>--</number:text>
        </number:boolean-style>
    
    so an implementation correctly reading such (e.g. now upcoming
    LibreOffice 7.4) would create a format "--" and display that for any
    value, true or false.
    
     This is a combination of 3 commits.
    
    Related: tdf#149484 Display BOOLEAN literal string text additions
    
    xChange-Id: Ifbaf0b18178091c3a340a7c4bc66f78397aadc18
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135506
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 2932dc7aa0c1239d39e060e6b7627317f1305549)
    
    Resolves: tdf#149484 Read and handle <number:text> in <number:boolean-style>
    
    xChange-Id: I1be5f2be908eb88aa4ef7436ea7c09f35b076acf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135507
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 025231224b8b076e280235cd2b943addd2fb0755)
    
    Related: tdf#149484 Write proper <number:boolean-style> with <number:text>
    
    xChange-Id: I46b7987dde25840ae0b6e5871b14e3806c6e4ac8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135508
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit 33a8c4bd0e8533ab42894280e7e04c13a47aefa9)
    
    Change-Id: I1be5f2be908eb88aa4ef7436ea7c09f35b076acf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135586
    Tested-by: Jenkins
    Reviewed-by: Adolfo Jayme Barrientos <fit...@ubuntu.com>

diff --git a/include/svl/zformat.hxx b/include/svl/zformat.hxx
index cd04f96ac8a1..ae57f5c868ed 100644
--- a/include/svl/zformat.hxx
+++ b/include/svl/zformat.hxx
@@ -696,6 +696,10 @@ private:
     SVL_DLLPRIVATE static void ImpAppendEraG( OUStringBuffer& OutStringBuffer, 
const CalendarWrapper& rCal,
                                               sal_Int16 nNatNum );
 
+    SVL_DLLPRIVATE bool ImpGetLogicalOutput( double fNumber,
+                                             sal_uInt16 nIx,
+                                             OUStringBuffer& OutString );
+
     SVL_DLLPRIVATE bool ImpGetNumberOutput( double fNumber,
                                             sal_uInt16 nIx,
                                             OUStringBuffer& OutString );
diff --git a/svl/source/numbers/zformat.cxx b/svl/source/numbers/zformat.cxx
index 34e439ee4921..fb9cbf50493d 100644
--- a/svl/source/numbers/zformat.cxx
+++ b/svl/source/numbers/zformat.cxx
@@ -2448,7 +2448,7 @@ bool SvNumberformat::GetOutputString(double fNumber,
     bool bRes = false;
     OutString.clear();
     *ppColor = nullptr; // No color change
-    if (eType & SvNumFormatType::LOGICAL)
+    if (eType & SvNumFormatType::LOGICAL && sFormatstring == 
rScan.GetKeywords()[NF_KEY_BOOLEAN])
     {
         if (fNumber)
         {
@@ -2614,6 +2614,9 @@ bool SvNumberformat::GetOutputString(double fNumber,
         case SvNumFormatType::CURRENCY:
             bRes |= ImpGetNumberOutput(fNumber, nIx, sBuff);
             break;
+        case SvNumFormatType::LOGICAL:
+            bRes |= ImpGetLogicalOutput(fNumber, nIx, sBuff);
+            break;
         case SvNumFormatType::FRACTION:
             bRes |= ImpGetFractionOutput(fNumber, nIx, sBuff);
             break;
@@ -4286,6 +4289,29 @@ bool SvNumberformat::ImpGetDateTimeOutput(double fNumber,
     return bRes;
 }
 
+bool SvNumberformat::ImpGetLogicalOutput(double fNumber,
+                                         sal_uInt16 nIx,
+                                         OUStringBuffer& sStr)
+{
+    bool bRes = false;
+    const ImpSvNumberformatInfo& rInfo = NumFor[nIx].Info();
+    const sal_uInt16 nCnt = NumFor[nIx].GetCount();
+    for (sal_uInt16 j = 0; j < nCnt; ++j)
+    {
+        switch (rInfo.nTypeArray[j])
+        {
+            case NF_KEY_BOOLEAN:
+                sStr.append( fNumber ? rScan.GetTrueString() : 
rScan.GetFalseString());
+            break;
+            case NF_SYMBOLTYPE_STRING:
+                sStr.append( rInfo.sStrArray[j]);
+            break;
+        }
+    }
+    impTransliterate(sStr, NumFor[nIx].GetNatNum());
+    return bRes;
+}
+
 bool SvNumberformat::ImpGetNumberOutput(double fNumber,
                                         sal_uInt16 nIx,
                                         OUStringBuffer& sStr)
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
index 4c313538b0df..3b68b5ae3c64 100644
--- a/xmloff/source/style/xmlnumfe.cxx
+++ b/xmloff/source/style/xmlnumfe.cxx
@@ -1253,6 +1253,37 @@ void SvXMLNumFmtExport::ExportPart_Impl( const 
SvNumberformat& rFormat, sal_uInt
         WriteBooleanElement_Impl();
         bAnyContent = true;
     }
+    else if (eType == XML_BOOLEAN_STYLE)
+    {
+        // <number:boolean-style> may contain only <number:boolean> and
+        // <number:text> elements.
+        sal_uInt16 nPos = 0;
+        bool bEnd = false;
+        while (!bEnd)
+        {
+            const short nElemType = rFormat.GetNumForType( nPart, nPos );
+            switch (nElemType)
+            {
+                case 0:
+                    bEnd = true;                // end of format reached
+                    if (bHasText && sTextContent.isEmpty())
+                        bHasText = false;       // don't write trailing empty 
text
+                break;
+                case NF_SYMBOLTYPE_STRING:
+                    {
+                        const OUString* pElemStr = rFormat.GetNumForString( 
nPart, nPos );
+                        if (pElemStr)
+                            AddToTextElement_Impl( *pElemStr );
+                    }
+                break;
+                case NF_KEY_BOOLEAN:
+                    WriteBooleanElement_Impl();
+                    bAnyContent = true;
+                break;
+            }
+            ++nPos;
+        }
+    }
     else
     {
         //  first loop to collect attributes
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
index 87f653873904..b21a01bea644 100644
--- a/xmloff/source/style/xmlnumfi.cxx
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -497,8 +497,11 @@ static bool lcl_ValidChar( sal_Unicode cChar, const 
SvXMLNumFormatContext& rPare
     }
 
     //  see ImpSvNumberformatScan::Next_Symbol
+
+    // All format types except BOOLEAN may contain minus sign or delimiter.
     if ( cChar == '-' )
-        return true;   // all format types may content minus sign or delimiter
+        return nFormatType != SvXMLStylesTokens::BOOLEAN_STYLE;
+
     if ( ( cChar == ' ' ||
            cChar == '/' ||
            cChar == '.' ||
@@ -528,11 +531,13 @@ static void lcl_EnquoteIfNecessary( OUStringBuffer& 
rContent, const SvXMLNumForm
 {
     bool bQuote = true;
     sal_Int32 nLength = rContent.getLength();
+    const SvXMLStylesTokens nFormatType = rParent.GetType();
 
-    if ((nLength == 1 && lcl_ValidChar( rContent[0], rParent)) ||
-            (nLength == 2 &&
-             ((rContent[0] == ' ' && rContent[1] == '-') ||
-              (rContent[1] == ' ' && lcl_ValidChar( rContent[0], rParent)))))
+    if (nFormatType != SvXMLStylesTokens::BOOLEAN_STYLE &&
+            ((nLength == 1 && lcl_ValidChar( rContent[0], rParent)) ||
+             (nLength == 2 &&
+              ((rContent[0] == ' ' && rContent[1] == '-') ||
+               (rContent[1] == ' ' && lcl_ValidChar( rContent[0], rParent))))))
     {
         //  Don't quote single separator characters like space or percent,
         //  or separator characters followed by space (used in date formats).
@@ -541,7 +546,7 @@ static void lcl_EnquoteIfNecessary( OUStringBuffer& 
rContent, const SvXMLNumForm
         //  the difference of quotes.
         bQuote = false;
     }
-    else if ( rParent.GetType() == SvXMLStylesTokens::PERCENTAGE_STYLE && 
nLength > 1 )
+    else if ( nFormatType == SvXMLStylesTokens::PERCENTAGE_STYLE && nLength > 
1 )
     {
         //  the percent character in percentage styles must be left out of 
quoting
         //  (one occurrence is enough even if there are several percent 
characters in the string)
@@ -906,7 +911,7 @@ void SvXMLNumFmtElementContext::endFastElement(sal_Int32 )
             }
             break;
         case SvXMLStyleTokens::Boolean:
-            // ignored - only default boolean format is supported
+            rParent.AddNfKeyword( NF_KEY_BOOLEAN );
             break;
 
         case SvXMLStyleTokens::Day:
@@ -1533,9 +1538,8 @@ sal_Int32 
SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter)
             nIndex = pFormatter->GetFormatIndex( NF_NUMBER_SYSTEM, nFormatLang 
);
     }
 
-    //  boolean is always the builtin boolean format
-    //  (no other boolean formats are implemented)
-    if ( nType == SvXMLStylesTokens::BOOLEAN_STYLE )
+    if ( nType == SvXMLStylesTokens::BOOLEAN_STYLE && !bHasExtraText &&
+            aMyConditions.empty() && sFormat.toChar() != '[' )
         nIndex = pFormatter->GetFormatIndex( NF_BOOLEAN, nFormatLang );
 
     //  check for default date formats
commit 3ac2a496343a5e94b0c2251783aa4932d651c720
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Fri Jun 10 00:01:23 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:24 2022 +0200

    Resolves: tdf#148072 Restore sheet-local names for Undo of Cut
    
    Undo of Cut uses CopyToTable() and not UndoToTab() as Copy does,
    so copy the sheet-local names also *from* Undo and not only *to*
    Undo. And mark for ScAreasChanged broadcast.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135568
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit b7eddf3e9c2db503dde632b35513844806be3c36)
    
     Conflicts:
            sc/source/core/data/table2.cxx
    
    Change-Id: Ib07f711a7d407dafdf548873291f1ccc81b85d47
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135587
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx
index 32c1e34bbff4..543944c18a25 100644
--- a/sc/source/core/data/table2.cxx
+++ b/sc/source/core/data/table2.cxx
@@ -1315,13 +1315,21 @@ void ScTable::CopyToTable(
     if (!ValidColRow(nCol1, nRow1) || !ValidColRow(nCol2, nRow2))
         return;
 
-    bool bIsUndoDoc = pDestTab->rDocument.IsUndo();
+    const bool bToUndoDoc = pDestTab->rDocument.IsUndo();
+    const bool bFromUndoDoc = rDocument.IsUndo();
 
-    if (bIsUndoDoc && (nFlags & InsertDeleteFlags::CONTENTS))
+    if ((bToUndoDoc || bFromUndoDoc) && (nFlags & InsertDeleteFlags::CONTENTS) 
&& mpRangeName)
     {
         // Copying formulas may create sheet-local named expressions on the
         // destination sheet. Add existing to Undo first.
+        // During Undo restore the previous named expressions.
         pDestTab->SetRangeName( std::unique_ptr<ScRangeName>( new ScRangeName( 
*GetRangeName())));
+        if (!pDestTab->rDocument.IsClipOrUndo())
+        {
+            ScDocShell* pDocSh = 
static_cast<ScDocShell*>(pDestTab->rDocument.GetDocumentShell());
+            if (pDocSh)
+                pDocSh->SetAreasChangedNeedBroadcast();
+        }
     }
 
     if (nFlags != InsertDeleteFlags::NONE)
@@ -1333,14 +1341,14 @@ void ScTable::CopyToTable(
         // quadratically expensive with large groups. So do the grouping just 
once at the end.
         sc::DelayFormulaGroupingSwitch delayGrouping( pDestTab->rDocument, 
true );
         for (SCCOL i = nCol1; i <= ClampToAllocatedColumns(nCol2); i++)
-            aCol[i].CopyToColumn(rCxt, nRow1, nRow2, bIsUndoDoc ? nFlags : 
nTempFlags, bMarked,
+            aCol[i].CopyToColumn(rCxt, nRow1, nRow2, bToUndoDoc ? nFlags : 
nTempFlags, bMarked,
                                  pDestTab->CreateColumnIfNotExists(i), 
pMarkData, bAsLink, bGlobalNamesToLocal);
     }
 
     if (!bColRowFlags)      // Column widths/Row heights/Flags
         return;
 
-    if(bIsUndoDoc && (nFlags & InsertDeleteFlags::ATTRIB))
+    if (bToUndoDoc && (nFlags & InsertDeleteFlags::ATTRIB))
     {
         pDestTab->mpCondFormatList.reset(new 
ScConditionalFormatList(pDestTab->rDocument, *mpCondFormatList));
     }
@@ -1453,7 +1461,7 @@ void ScTable::CopyToTable(
         CopySparklinesToTable(nCol1, nRow1, nCol2, nRow2, pDestTab);
     }
 
-    if (!bIsUndoDoc && bCopyCaptions && (nFlags & (InsertDeleteFlags::NOTE | 
InsertDeleteFlags::ADDNOTES)))
+    if (!bToUndoDoc && bCopyCaptions && (nFlags & (InsertDeleteFlags::NOTE | 
InsertDeleteFlags::ADDNOTES)))
     {
         bool bCloneCaption = (nFlags & InsertDeleteFlags::NOCAPTIONS) == 
InsertDeleteFlags::NONE;
         CopyCaptionsToTable( nCol1, nRow1, nCol2, nRow2, pDestTab, 
bCloneCaption);
commit c9ffec6cdf1af4c9c1e8c6317a59ad5d63093ac7
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Mon May 30 21:38:41 2022 +0200
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Jun 27 13:30:24 2022 +0200

    InsertMatrixFormula: correct references for across sheets array formulas
    
    Inserting an array/matrix formula across two or more
    selected/marked sheets generated wrong matrix offset references
    starting with the second sheet, pointing to the top left of the
    first array formula. Only the top left cell of the inserted
    formula on each sheet displayed the correct value. Deleting the
    array formula on the first sheet then left all matrix offset
    references on the remaining sheets with #REF! errors and those
    cells could not be deleted anymore because their original parent
    cell was gone.
    
    Change-Id: If5d53311f9aabdcd7432ff26ab555bb91b0b121d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135147
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit dfd5081ff3973d5d0f216b06dda6360fa490cc9c)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/135154
    Reviewed-by: Caolán McNamara <caol...@redhat.com>

diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx
index cf9a2fbd0a83..e893c84acaed 100644
--- a/sc/source/core/data/documen4.cxx
+++ b/sc/source/core/data/documen4.cxx
@@ -306,13 +306,11 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW 
nRow1,
                     *pCell, *this, ScAddress(nCol1, nRow1, rTab), 
ScCloneFlags::StartListening));
     }
 
-    ScAddress aBasePos(nCol1, nRow1, nTab1);
     ScSingleRefData aRefData;
     aRefData.InitFlags();
-    aRefData.SetColRel( true );
-    aRefData.SetRowRel( true );
-    aRefData.SetTabRel( true );
-    aRefData.SetAddress(GetSheetLimits(), aBasePos, aBasePos);
+    aRefData.SetRelCol(0);
+    aRefData.SetRelRow(0);
+    aRefData.SetRelTab(0);  // 2D matrix, always same sheet
 
     ScTokenArray aArr(*this); // consists only of one single reference token.
     formula::FormulaToken* t = aArr.AddMatrixSingleReference(aRefData);
@@ -326,26 +324,21 @@ void ScDocument::InsertMatrixFormula(SCCOL nCol1, SCROW 
nRow1,
         if (!pTab)
             continue;
 
-        if (nTab != nTab1)
-        {
-            aRefData.SetRelTab(nTab - aBasePos.Tab());
-            *t->GetSingleRef() = aRefData;
-        }
-
-        for (SCCOL nCol : GetWritableColumnsRange(nTab1, nCol1, nCol2))
+        for (SCCOL nCol : GetWritableColumnsRange(nTab, nCol1, nCol2))
         {
+            aRefData.SetRelCol(nCol1 - nCol);
             for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
             {
                 if (nCol == nCol1 && nRow == nRow1)
                     // Skip the base position.
                     continue;
 
-                // Token array must be cloned so that each formula cell 
receives its own copy.
-                aPos = ScAddress(nCol, nRow, nTab);
                 // Reference in each cell must point to the origin cell 
relative to the current cell.
-                aRefData.SetAddress(GetSheetLimits(), aBasePos, aPos);
+                aRefData.SetRelRow(nRow1 - nRow);
                 *t->GetSingleRef() = aRefData;
+                // Token array must be cloned so that each formula cell 
receives its own copy.
                 std::unique_ptr<ScTokenArray> pTokArr(aArr.Clone());
+                aPos = ScAddress(nCol, nRow, nTab);
                 pCell = new ScFormulaCell(*this, aPos, *pTokArr, eGram, 
ScMatrixMode::Reference);
                 pTab->SetFormulaCell(nCol, nRow, pCell);
             }

Reply via email to