include/xmloff/xmlnumfe.hxx      |    3 ++-
 include/xmloff/xmlnumfi.hxx      |    2 ++
 xmloff/source/style/xmlnumfe.cxx |   16 +++++++++++++---
 xmloff/source/style/xmlnumfi.cxx |   20 ++++++++++++++++++++
 4 files changed, 37 insertions(+), 4 deletions(-)

New commits:
commit 5d6a91b8ea40ec79c746e5c1d486be6e25a2856d
Author:     Eike Rathke <er...@redhat.com>
AuthorDate: Sun Aug 22 22:13:23 2021 +0200
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Aug 25 09:54:38 2021 +0200

    Resolves: tdf#143979 Write and read empty text element in number formats
    
    ... as they may be significant as separators between keywords of
    same letters.
    
    Also strip trailing empty text as meaningless, except if the only
    element.
    
    >General;General<
    earlier both General were written as
    
        <number:number-style style:name="N111P0" style:volatile="true">
          <number:number number:min-integer-digits="1"/>
          <number:text/>
        </number:number-style>
    
    for which now <number:text> is not.
    
    Change-Id: I4809b1c784667994303b49d8e4ab0e857367e2cb
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120856
    Reviewed-by: Eike Rathke <er...@redhat.com>
    Tested-by: Jenkins
    (cherry picked from commit c6f15d228489ccfd0628ca80b45a5c2faaacc7d3)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120728
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/include/xmloff/xmlnumfe.hxx b/include/xmloff/xmlnumfe.hxx
index 98584ac93873..28bfe8d1a2ad 100644
--- a/include/xmloff/xmlnumfe.hxx
+++ b/include/xmloff/xmlnumfe.hxx
@@ -50,7 +50,8 @@ private:
     SvXMLExport&                rExport;
     OUString                    sPrefix;
     SvNumberFormatter*          pFormatter;
-    OUStringBuffer       sTextContent;
+    OUStringBuffer              sTextContent;
+    bool                        bHasText;
     std::unique_ptr<SvXMLNumUsedList_Impl>      pUsedList;
     std::unique_ptr<CharClass>                  pCharClass;
     std::unique_ptr<LocaleDataWrapper>          pLocaleData;
diff --git a/include/xmloff/xmlnumfi.hxx b/include/xmloff/xmlnumfi.hxx
index 0f6384f3b785..8026b4e1846b 100644
--- a/include/xmloff/xmlnumfi.hxx
+++ b/include/xmloff/xmlnumfi.hxx
@@ -145,6 +145,7 @@ private:
     bool            bAutoDec;       // set in AddNumber
     bool            bAutoInt;       // set in AddNumber
     bool            bHasExtraText;
+    bool            bHasTrailingEmptyText;
     OUStringBuffer aFormatCode{64};
     OUStringBuffer aConditions{32};
     bool            bHasLongDoW;
@@ -189,6 +190,7 @@ public:
 
     bool HasLongDoW() const                     { return bHasLongDoW; }
     void SetHasLongDoW(bool bSet)               { bHasLongDoW = bSet; }
+    void SetHasTrailingEmptyText(bool bSet)     { bHasTrailingEmptyText = 
bSet; }
 
     void UpdateCalendar( const OUString& rNewCalendar );
     ImplicitCalendar GetImplicitCalendarState() const { return 
eImplicitCalendar; }
diff --git a/xmloff/source/style/xmlnumfe.cxx b/xmloff/source/style/xmlnumfe.cxx
index 38c4d42d2986..59e6e8d9bf5c 100644
--- a/xmloff/source/style/xmlnumfe.cxx
+++ b/xmloff/source/style/xmlnumfe.cxx
@@ -209,7 +209,8 @@ SvXMLNumFmtExport::SvXMLNumFmtExport(
             const uno::Reference< util::XNumberFormatsSupplier >& rSupp ) :
     rExport( rExp ),
     sPrefix( OUString("N") ),
-    pFormatter( nullptr )
+    pFormatter( nullptr ),
+    bHasText( false )
 {
     //  supplier must be SvNumberFormatsSupplierObj
     SvNumberFormatsSupplierObj* pObj =
@@ -241,7 +242,8 @@ SvXMLNumFmtExport::SvXMLNumFmtExport(
                        const OUString& rPrefix ) :
     rExport( rExp ),
     sPrefix( rPrefix ),
-    pFormatter( nullptr )
+    pFormatter( nullptr ),
+    bHasText( false )
 {
     //  supplier must be SvNumberFormatsSupplierObj
     SvNumberFormatsSupplierObj* pObj =
@@ -319,16 +321,21 @@ void SvXMLNumFmtExport::AddToTextElement_Impl( 
std::u16string_view rString )
     //  to avoid several text elements following each other
 
     sTextContent.append( rString );
+    // Also empty string leads to a number:text element as it may separate
+    // keywords of the same letter (e.g. MM""MMM) that otherwise would be
+    // concatenated when reading back in.
+    bHasText = true;
 }
 
 void SvXMLNumFmtExport::FinishTextElement_Impl(bool bUseExtensionNS)
 {
-    if ( !sTextContent.isEmpty() )
+    if ( bHasText )
     {
         sal_uInt16 nNS = bUseExtensionNS ? XML_NAMESPACE_LO_EXT : 
XML_NAMESPACE_NUMBER;
         SvXMLElementExport aElem( rExport, nNS, XML_TEXT,
                                   true, false );
         rExport.Characters( sTextContent.makeStringAndClear() );
+        bHasText = false;
     }
 }
 
@@ -1414,6 +1421,8 @@ void SvXMLNumFmtExport::ExportPart_Impl( const 
SvNumberformat& rFormat, sal_uInt
             {
                 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:
                 case NF_SYMBOLTYPE_DATESEP:
@@ -1462,6 +1471,7 @@ void SvXMLNumFmtExport::ExportPart_Impl( const 
SvNumberformat& rFormat, sal_uInt
                     break;
                 case NF_KEY_GENERAL :
                         WriteNumberElement_Impl( -1, -1, 1, OUString(), false, 
0, aEmbeddedEntries );
+                        bAnyContent = true;
                     break;
                 case NF_KEY_CCC:
                     if (pElemStr)
diff --git a/xmloff/source/style/xmlnumfi.cxx b/xmloff/source/style/xmlnumfi.cxx
index f7cabc5fa29f..7af3a7e20705 100644
--- a/xmloff/source/style/xmlnumfi.cxx
+++ b/xmloff/source/style/xmlnumfi.cxx
@@ -878,6 +878,13 @@ void SvXMLNumFmtElementContext::endFastElement(sal_Int32 )
                 lcl_EnquoteIfNecessary( aContent, rParent );
                 rParent.AddToCode( aContent.makeStringAndClear() );
             }
+            else
+            {
+                // Quoted empty text may be significant to separate.
+                aContent.append("\"\"");
+                rParent.AddToCode( aContent.makeStringAndClear() );
+                rParent.SetHasTrailingEmptyText(true);  // *after* AddToCode()
+            }
             break;
 
         case SvXMLStyleTokens::Number:
@@ -1131,6 +1138,7 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( 
SvXMLImport& rImport,
     bAutoDec( false ),
     bAutoInt( false ),
     bHasExtraText( false ),
+    bHasTrailingEmptyText( false ),
     bHasLongDoW( false ),
     bHasDateTime( false ),
     bRemoveAfterUse( false ),
@@ -1267,6 +1275,7 @@ SvXMLNumFormatContext::SvXMLNumFormatContext( 
SvXMLImport& rImport,
     bAutoDec( false ),
     bAutoInt( false ),
     bHasExtraText( false ),
+    bHasTrailingEmptyText( false ),
     bHasLongDoW( false ),
     bHasDateTime( false ),
     bRemoveAfterUse( false ),
@@ -1486,12 +1495,22 @@ sal_Int32 
SvXMLNumFormatContext::CreateAndInsert(SvNumberFormatter* pFormatter)
         }
     }
 
+    sal_Int32 nBufLen;
     if ( aFormatCode.isEmpty() )
     {
         //  insert empty format as empty string (with quotes)
         //  #93901# this check has to be done before inserting the conditions
         aFormatCode.append("\"\"");    // ""
     }
+    else if (bHasTrailingEmptyText && (nBufLen = aFormatCode.getLength()) >= 3)
+    {
+        // Remove a trailing empty text. Earlier this may had been written to
+        // file, like in "General;General" written with elements for
+        // 'General"";General""' (whyever); when reading, empty text was
+        // ignored, which it isn't anymore, so get rid of those.
+        if (aFormatCode[nBufLen-1] == '"' && aFormatCode[nBufLen-2] == '"')
+            aFormatCode.truncate( nBufLen - 2);
+    }
 
     aFormatCode.insert( 0, aConditions.makeStringAndClear() );
     OUString sFormat = aFormatCode.makeStringAndClear();
@@ -1631,6 +1650,7 @@ void SvXMLNumFormatContext::AddToCode( 
std::u16string_view rString )
 {
     aFormatCode.append( rString );
     bHasExtraText = true;
+    bHasTrailingEmptyText = false;  // is set by caller again if so
 }
 
 void SvXMLNumFormatContext::AddNumber( const SvXMLNumberInfo& rInfo )

Reply via email to