cui/source/tabpages/numpages.cxx                              |   43 +-
 include/com/sun/star/uno/Any.h                                |    4 
 include/com/sun/star/uno/Any.hxx                              |    8 
 sw/qa/extras/ooxmlimport/data/tdf154319-ToC_with_s_and_d.docx |binary
 sw/qa/extras/ooxmlimport/ooxmlimport2.cxx                     |   50 +++
 writerfilter/source/dmapper/DomainMapper_Impl.cxx             |  150 ++++++----
 6 files changed, 187 insertions(+), 68 deletions(-)

New commits:
commit 128671288204136ceba258a5fe809c354728a175
Author:     Mike Kaganski <mike.kagan...@collabora.com>
AuthorDate: Tue Mar 21 21:35:58 2023 +0300
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri Mar 24 09:02:52 2023 +0000

    tdf#154319: fix TOC field codes parsing
    
    Change-Id: I734697f52df14ca5b316481df8a58fef72ab9571
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149254
    Tested-by: Jenkins
    Reviewed-by: Mike Kaganski <mike.kagan...@collabora.com>
    (cherry picked from commit 76777c82fa4bb5080c135e2241c3f7122dcbb298)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149437
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/include/com/sun/star/uno/Any.h b/include/com/sun/star/uno/Any.h
index f232ccd90fe9..b453f5fa5b0c 100644
--- a/include/com/sun/star/uno/Any.h
+++ b/include/com/sun/star/uno/Any.h
@@ -451,6 +451,10 @@ template<>
 inline bool SAL_CALL operator >>= ( const Any & rAny, ::rtl::OUString & value 
);
 template<>
 inline bool SAL_CALL operator == ( const Any & rAny, const ::rtl::OUString & 
value );
+#if defined LIBO_INTERNAL_ONLY
+template<std::size_t N>
+inline bool SAL_CALL operator == (const Any& rAny, const 
rtl::OUStringLiteral<N>& value);
+#endif
 // type
 template<>
 inline bool SAL_CALL operator >>= ( const Any & rAny, Type & value );
diff --git a/include/com/sun/star/uno/Any.hxx b/include/com/sun/star/uno/Any.hxx
index d73b2a586d61..6267d41e733c 100644
--- a/include/com/sun/star/uno/Any.hxx
+++ b/include/com/sun/star/uno/Any.hxx
@@ -600,6 +600,14 @@ inline bool SAL_CALL operator == ( const Any & rAny, const 
::rtl::OUString & val
     return (typelib_TypeClass_STRING == rAny.pType->eTypeClass &&
             value == * static_cast< const ::rtl::OUString * >( rAny.pData ) );
 }
+
+#if defined LIBO_INTERNAL_ONLY
+template<std::size_t N>
+inline bool SAL_CALL operator == (const Any& rAny, const 
rtl::OUStringLiteral<N>& value)
+{
+    return operator ==(rAny, rtl::OUString(value));
+}
+#endif
 // type
 
 template<>
diff --git a/sw/qa/extras/ooxmlimport/data/tdf154319-ToC_with_s_and_d.docx 
b/sw/qa/extras/ooxmlimport/data/tdf154319-ToC_with_s_and_d.docx
new file mode 100644
index 000000000000..dc5a67824c9d
Binary files /dev/null and 
b/sw/qa/extras/ooxmlimport/data/tdf154319-ToC_with_s_and_d.docx differ
diff --git a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx 
b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
index 26ad31df3a78..406812ab7fa5 100644
--- a/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
+++ b/sw/qa/extras/ooxmlimport/ooxmlimport2.cxx
@@ -1021,6 +1021,56 @@ CPPUNIT_TEST_FIXTURE(Test, testTdf153791)
     CPPUNIT_ASSERT_EQUAL(COL_AUTO, getProperty<Color>(xRun, "CharColor"));
 }
 
+CPPUNIT_TEST_FIXTURE(Test, testTdf154319)
+{
+    createSwDoc("tdf154319-ToC_with_s_and_d.docx");
+
+    css::uno::Reference<css::text::XDocumentIndexesSupplier> 
xSupplier(mxComponent,
+                                                                       
css::uno::UNO_QUERY_THROW);
+    auto xIndexes = xSupplier->getDocumentIndexes();
+    css::uno::Reference<css::beans::XPropertySet> 
xTOCIndex(xIndexes->getByIndex(0),
+                                                            
css::uno::UNO_QUERY_THROW);
+    css::uno::Reference<css::container::XIndexReplace> xLevelFormats;
+    CPPUNIT_ASSERT(xTOCIndex->getPropertyValue("LevelFormat") >>= 
xLevelFormats);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(11), xLevelFormats->getCount());
+
+    const auto checkPropVal = [](const auto& expected, const 
css::beans::PropertyValues& entry,
+                                 const OUString& name) {
+        auto it
+            = std::find_if(entry.begin(), entry.end(),
+                           [&name](const css::beans::PropertyValue& p) { 
return p.Name == name; });
+        OString msg = "Property: " + name.toUtf8();
+        CPPUNIT_ASSERT_MESSAGE(msg.getStr(), it != entry.end());
+        CPPUNIT_ASSERT_EQUAL_MESSAGE(msg.getStr(), css::uno::Any(expected), 
it->Value);
+    };
+
+    //start with level 1, 0 is the header level
+    for (sal_Int32 nLevel = 1; nLevel < xLevelFormats->getCount(); ++nLevel)
+    {
+        css::uno::Sequence<css::beans::PropertyValues> aLevel;
+        xLevelFormats->getByIndex(nLevel) >>= aLevel;
+
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(8), aLevel.getLength());
+
+        checkPropVal(OUString("TokenHyperlinkStart"), aLevel[0], "TokenType");
+
+        checkPropVal(OUString("TokenEntryNumber"), aLevel[1], "TokenType");
+
+        checkPropVal(OUString("TokenEntryText"), aLevel[2], "TokenType");
+
+        checkPropVal(OUString("TokenTabStop"), aLevel[3], "TokenType");
+
+        checkPropVal(OUString("TokenChapterInfo"), aLevel[4], "TokenType");
+
+        checkPropVal(OUString("TokenText"), aLevel[5], "TokenType");
+        checkPropVal(OUString("\""), aLevel[5], "Text");
+
+        checkPropVal(OUString("TokenPageNumber"), aLevel[6], "TokenType");
+
+        checkPropVal(OUString("TokenHyperlinkEnd"), aLevel[7], "TokenType");
+    }
+}
+
 // tests should only be added to ooxmlIMPORT *if* they fail round-tripping in 
ooxmlEXPORT
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/writerfilter/source/dmapper/DomainMapper_Impl.cxx 
b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
index 449c75e9b8ce..663e47a1fa70 100644
--- a/writerfilter/source/dmapper/DomainMapper_Impl.cxx
+++ b/writerfilter/source/dmapper/DomainMapper_Impl.cxx
@@ -4752,26 +4752,52 @@ static OUString lcl_ExtractVariableAndHint( 
std::u16string_view rCommand, OUStri
     return OUString(sRet);
 }
 
+static size_t nextCode(std::u16string_view rCommand, size_t pos)
+{
+    bool inQuotes = false;
+    for (; pos < rCommand.size(); ++pos)
+    {
+        switch (rCommand[pos])
+        {
+        case '"':
+            inQuotes = !inQuotes;
+            break;
+        case '\\':
+            ++pos;
+            if (!inQuotes)
+                return pos;
+            break;
+        }
+    }
+    return std::u16string_view::npos;
+}
+
+// Returns the position of the field code
+static size_t findCode(std::u16string_view rCommand, sal_Unicode cSwitch)
+{
+    for (size_t i = nextCode(rCommand, 0); i < rCommand.size(); i = 
nextCode(rCommand, i))
+        if (rCommand[i] == cSwitch)
+            return i;
+
+    return std::u16string_view::npos;
+}
 
 static bool lcl_FindInCommand(
     std::u16string_view rCommand,
     sal_Unicode cSwitch,
     OUString& rValue )
 {
-    bool bRet = false;
-    OUString sSearch = "\\" + OUStringChar( cSwitch );
-    size_t nIndex = rCommand.find( sSearch  );
-    if( nIndex != std::u16string_view::npos )
-    {
-        bRet = true;
-        //find next '\' or end of string
-        size_t nEndIndex = rCommand.find( '\\', nIndex + 1);
-        if( nEndIndex == std::u16string_view::npos )
-            nEndIndex = rCommand.size() ;
-        if( nEndIndex - nIndex > 3 )
-            rValue = rCommand.substr( nIndex + 3, nEndIndex - nIndex - 3);
+    if (size_t i = findCode(rCommand, cSwitch); i < rCommand.size())
+    {
+        ++i;
+        size_t next = nextCode(rCommand, i);
+        if (next < rCommand.size())
+            --next; // get back before the next '\\'
+        rValue = o3tl::trim(rCommand.substr(i, next - i));
+        return true;
     }
-    return bRet;
+
+    return false;
 }
 
 static OUString lcl_trim(std::u16string_view sValue)
@@ -6005,45 +6031,49 @@ void DomainMapper_Impl::handleAuthor
 static uno::Sequence< beans::PropertyValues > lcl_createTOXLevelHyperlinks( 
bool bHyperlinks, const OUString& sChapterNoSeparator,
                                    const uno::Sequence< beans::PropertyValues 
>& aLevel )
 {
-    //create a copy of the level and add two new entries - hyperlink start and 
end
-    bool bChapterNoSeparator  = !sChapterNoSeparator.isEmpty();
-    sal_Int32 nAdd = (bHyperlinks && bChapterNoSeparator) ? 4 : 2;
-    uno::Sequence< beans::PropertyValues > aNewLevel( aLevel.getLength() + 
nAdd);
-    beans::PropertyValues* pNewLevel = aNewLevel.getArray();
-    if( bHyperlinks )
-    {
-        beans::PropertyValues aHyperlink{ comphelper::makePropertyValue(
-            getPropertyName( PROP_TOKEN_TYPE ), getPropertyName( 
PROP_TOKEN_HYPERLINK_START )) };
-        pNewLevel[0] = aHyperlink;
-        aHyperlink = { comphelper::makePropertyValue(
-            getPropertyName(PROP_TOKEN_TYPE), getPropertyName( 
PROP_TOKEN_HYPERLINK_END )) };
-        pNewLevel[aNewLevel.getLength() -1] = aHyperlink;
-    }
-    if( bChapterNoSeparator )
-    {
-        beans::PropertyValues aChapterNo{
-            comphelper::makePropertyValue(getPropertyName( PROP_TOKEN_TYPE ),
-                                          getPropertyName( 
PROP_TOKEN_CHAPTER_INFO )),
-            comphelper::makePropertyValue(getPropertyName( PROP_CHAPTER_FORMAT 
),
-                                          //todo: is ChapterFormat::Number 
correct?
-                                          
sal_Int16(text::ChapterFormat::NUMBER))
-        };
-        pNewLevel[aNewLevel.getLength() - (bHyperlinks ? 4 : 2) ] = aChapterNo;
+    //create a copy of the level and add new entries
 
-        beans::PropertyValues aChapterSeparator{
-            comphelper::makePropertyValue(getPropertyName( PROP_TOKEN_TYPE ),
-                                          getPropertyName( PROP_TOKEN_TEXT )),
-            comphelper::makePropertyValue(getPropertyName( PROP_TEXT ), 
sChapterNoSeparator)
-        };
-        pNewLevel[aNewLevel.getLength() - (bHyperlinks ? 3 : 1)] = 
aChapterSeparator;
+    std::vector<css::beans::PropertyValues> aNewLevel;
+    aNewLevel.reserve(aLevel.getLength() + 4); // at most 4 added items
+
+    static constexpr OUStringLiteral tokType(u"TokenType");
+    static constexpr OUStringLiteral tokHStart(u"TokenHyperlinkStart");
+    static constexpr OUStringLiteral tokHEnd(u"TokenHyperlinkEnd");
+    static constexpr OUStringLiteral tokPNum(u"TokenPageNumber");
+
+    if (bHyperlinks)
+        aNewLevel.push_back({ comphelper::makePropertyValue(tokType, 
tokHStart) });
+
+    for (const auto& item : aLevel)
+    {
+        if (bHyperlinks
+            && std::any_of(item.begin(), item.end(),
+                           [](const css::beans::PropertyValue& p) {
+                               return p.Name == tokType
+                                      && (p.Value == tokHStart || p.Value == 
tokHEnd);
+                           }))
+            continue; // We add hyperlink ourselves, so just skip existing 
hyperlink start / end
+
+        if (!sChapterNoSeparator.isEmpty()
+            && std::any_of(item.begin(), item.end(),
+                           [](const css::beans::PropertyValue& p)
+                           { return p.Name == tokType && p.Value == tokPNum; 
}))
+        {
+            // This is an existing page number token; insert the chapter and 
separator before it
+            aNewLevel.push_back(
+                { comphelper::makePropertyValue(tokType, 
OUString("TokenChapterInfo")),
+                  comphelper::makePropertyValue("ChapterFormat", 
text::ChapterFormat::NUMBER) });
+            aNewLevel.push_back({ comphelper::makePropertyValue(tokType, 
OUString("TokenText")),
+                                  comphelper::makePropertyValue("Text", 
sChapterNoSeparator) });
+        }
+
+        aNewLevel.push_back(item);
     }
-    //copy the 'old' entries except the last (page no)
-    std::copy(aLevel.begin(), std::prev(aLevel.end()), std::next(pNewLevel));
-    //copy page no entry (last or last but one depending on bHyperlinks
-    sal_Int32 nPageNo = aNewLevel.getLength() - (bHyperlinks ? 2 : 3);
-    pNewLevel[nPageNo] = aLevel[aLevel.getLength() - 1];
 
-    return aNewLevel;
+    if (bHyperlinks)
+        aNewLevel.push_back({ comphelper::makePropertyValue(tokType, tokHEnd) 
});
+
+    return comphelper::containerToSequence(aNewLevel);
 }
 
 /// Returns title of the TOC placed in paragraph(s) before TOC field inside 
STD-frame
@@ -6144,6 +6174,26 @@ static auto FilterChars(OUString const& rStyleName) -> 
OUString
     return ret.makeStringAndClear();
 }
 
+static OUString UnquoteFieldText(std::u16string_view s)
+{
+    OUStringBuffer result(s.size());
+    for (size_t i = 0; i < s.size(); ++i)
+    {
+        switch (s[i])
+        {
+        case '"':
+            continue;
+        case '\\':
+            if (i < s.size() - 1)
+                ++i;
+            [[fallthrough]];
+        default:
+            result.append(s[i]);
+        }
+    }
+    return result.makeStringAndClear();
+}
+
 OUString DomainMapper_Impl::ConvertTOCStyleName(OUString const& rTOCStyleName)
 {
     assert(!rTOCStyleName.isEmpty());
@@ -6209,7 +6259,7 @@ void DomainMapper_Impl::handleToc
     if( lcl_FindInCommand( pContext->GetCommand(), 'd', sValue ))
     {
                         //todo: insert the chapter number into each level and 
insert the separator additionally
-        sChapterNoSeparator = sValue;
+        sChapterNoSeparator = UnquoteFieldText(sValue);
     }
 //                  \f Builds a table of contents using TC entries instead of 
outline levels
     if( lcl_FindInCommand( pContext->GetCommand(), 'f', sValue ))
commit fde07de7155099e1bc1d718e0f82dc354ed96b0f
Author:     Rafael Lima <rafael.palma.l...@gmail.com>
AuthorDate: Fri Feb 24 15:23:48 2023 -0300
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Fri Mar 24 09:02:44 2023 +0000

    tdf#153808 Fix numbering preview in dark mode
    
    This patch fixes the color used for numbers and bullets in the preview
    of the Bullets and Numbering dialog in Impress. Currently the
    implementation causes the bullets and numbers to be rendered in white
    over a white background when using dark mode.
    
    The fix uses DOCCOLOR and FONTCOLOR to create the preview, instead of
    FieldColor and FieldTextColor.
    
    Change-Id: Icf41c5be59c67a2d68e3c520744276492e9baa59
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147664
    Tested-by: Jenkins
    Reviewed-by: Heiko Tietze <heiko.tie...@documentfoundation.org>
    (cherry picked from commit 3a4b32c9e1dfc56d9b00e3720834d21c9095f629)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149435
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

diff --git a/cui/source/tabpages/numpages.cxx b/cui/source/tabpages/numpages.cxx
index 0c66f69ee637..916e513d9cc0 100644
--- a/cui/source/tabpages/numpages.cxx
+++ b/cui/source/tabpages/numpages.cxx
@@ -44,6 +44,7 @@
 #include <unotools/pathoptions.hxx>
 #include <svtools/ctrltool.hxx>
 #include <svtools/unitconv.hxx>
+#include <svtools/colorcfg.hxx>
 #include <com/sun/star/style/NumberingType.hpp>
 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
 #include <com/sun/star/container/XIndexAccess.hpp>
@@ -2154,10 +2155,10 @@ static tools::Long lcl_DrawBullet(VirtualDevice* pVDev,
     aFont.SetFontSize(aTmpSize);
     aFont.SetTransparent(true);
     Color aBulletColor = rFmt.GetBulletColor();
-    if(aBulletColor == COL_AUTO)
-        aBulletColor = pVDev->GetFillColor().IsDark() ? COL_WHITE : COL_BLACK;
-    else if(aBulletColor == pVDev->GetFillColor())
-        aBulletColor.Invert();
+    if (aBulletColor == COL_AUTO)
+        aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : 
COL_BLACK;
+    else if (pVDev->GetBackgroundColor().IsDark() == aBulletColor.IsDark())
+        aBulletColor = pVDev->GetBackgroundColor().IsDark() ? COL_WHITE : 
COL_BLACK;
     aFont.SetColor(aBulletColor);
     pVDev->SetFont( aFont );
     sal_UCS4 cChar = rFmt.GetBulletChar();
@@ -2183,9 +2184,9 @@ void SvxNumberingPreview::Paint(vcl::RenderContext& 
rRenderContext, const ::tool
 {
     Size aSize(rRenderContext.PixelToLogic(GetOutputSizePixel()));
 
-    const StyleSettings& rStyleSettings = 
rRenderContext.GetSettings().GetStyleSettings();
-    const Color aBackColor = rStyleSettings.GetFieldColor();
-    const Color aTextColor = rStyleSettings.GetFieldTextColor();
+    // Use default document and font colors to create preview
+    const Color aBackColor = 
svtools::ColorConfig().GetColorValue(svtools::DOCCOLOR).nColor;
+    const Color aTextColor = 
svtools::ColorConfig().GetColorValue(svtools::FONTCOLOR).nColor;
 
     ScopedVclPtrInstance<VirtualDevice> pVDev(rRenderContext);
     pVDev->EnableRTL(rRenderContext.IsRTLEnabled());
@@ -2197,6 +2198,8 @@ void SvxNumberingPreview::Paint(vcl::RenderContext& 
rRenderContext, const ::tool
         aLineColor.Invert();
     pVDev->SetLineColor(aLineColor);
     pVDev->SetFillColor(aBackColor);
+    pVDev->SetBackground(Wallpaper(aBackColor));
+    pVDev->DrawWallpaper(pVDev->GetOutputRectPixel(), pVDev->GetBackground());
 
     if (pActNum)
     {
@@ -2224,6 +2227,9 @@ void SvxNumberingPreview::Paint(vcl::RenderContext& 
rRenderContext, const ::tool
 
         if (bPosition)
         {
+            // When bPosition == true, draw the preview used in the Writer's 
"Position" tab
+            // This is not used in Impress/Draw
+
             tools::Long nLineHeight = nFontHeight * 8 / 7;
             sal_uInt8 nStart = 0;
             while (!(nActLevel & (1<<nStart)))
@@ -2290,9 +2296,9 @@ void SvxNumberingPreview::Paint(vcl::RenderContext& 
rRenderContext, const ::tool
                     vcl::Font aColorFont(aSaveFont);
                     Color aTmpBulletColor = rFmt.GetBulletColor();
                     if (aTmpBulletColor == COL_AUTO)
-                        aTmpBulletColor = aBackColor.IsDark() ? COL_WHITE : 
COL_BLACK;
-                    else if (aTmpBulletColor == aBackColor)
-                        aTmpBulletColor.Invert();
+                        aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() 
? COL_WHITE : COL_BLACK;
+                    else if (pVDev->GetBackgroundColor().IsDark() == 
aTmpBulletColor.IsDark())
+                        aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() 
? COL_WHITE : COL_BLACK;
                     aColorFont.SetColor(aTmpBulletColor);
                     pVDev->SetFont(aColorFont);
                     pVDev->DrawText(Point(nNumberXPos, nYStart), aText);
@@ -2354,14 +2360,15 @@ void SvxNumberingPreview::Paint(vcl::RenderContext& 
rRenderContext, const ::tool
         }
         else
         {
+            // When bPosition == false, draw the preview used in Writer's 
"Customize" tab
+            // and in Impress' "Bullets and Numbering" dialog
+
             //#i5153# painting gray or black rectangles as 'normal' numbering 
text
             tools::Long nWidth = pVDev->GetTextWidth("Preview");
             tools::Long nTextHeight = pVDev->GetTextHeight();
             tools::Long nRectHeight = nTextHeight * 2 / 3;
             tools::Long nTopOffset = nTextHeight - nRectHeight;
-            Color aBlackColor(COL_BLACK);
-            if (aBlackColor == aBackColor)
-                aBlackColor.Invert();
+            Color aSelRectColor = pVDev->GetBackgroundColor().IsDark() ? 
COL_WHITE : COL_BLACK;
 
             for (sal_uInt16 nLevel = 0; nLevel < pActNum->GetLevelCount(); 
++nLevel, nYStart = nYStart + nYStep)
             {
@@ -2422,9 +2429,9 @@ void SvxNumberingPreview::Paint(vcl::RenderContext& 
rRenderContext, const ::tool
                     aFont.SetFontSize(aTmpSize);
                     Color aTmpBulletColor = rFmt.GetBulletColor();
                     if (aTmpBulletColor == COL_AUTO)
-                        aTmpBulletColor = aBackColor.IsDark() ? COL_WHITE : 
COL_BLACK;
-                    else if (aTmpBulletColor == aBackColor)
-                        aTmpBulletColor.Invert();
+                        aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() 
? COL_WHITE : COL_BLACK;
+                    else if (pVDev->GetBackgroundColor().IsDark() == 
aTmpBulletColor.IsDark())
+                        aTmpBulletColor = pVDev->GetBackgroundColor().IsDark() 
? COL_WHITE : COL_BLACK;
                     aFont.SetColor(aTmpBulletColor);
                     pVDev->SetFont(aFont);
                     aNum.SetLevel( nLevel );
@@ -2442,8 +2449,8 @@ void SvxNumberingPreview::Paint(vcl::RenderContext& 
rRenderContext, const ::tool
                 //#i5153# the selected rectangle(s) should be black
                 if (0 != (nActLevel & (1<<nLevel)))
                 {
-                    pVDev->SetFillColor( aBlackColor );
-                    pVDev->SetLineColor( aBlackColor );
+                    pVDev->SetFillColor( aSelRectColor );
+                    pVDev->SetLineColor( aSelRectColor );
                 }
                 else
                 {

Reply via email to