include/svx/nbdtmg.hxx                               |    3 
 include/svx/numvset.hxx                              |    7 +
 include/svx/svxids.hrc                               |    7 +
 sd/source/ui/func/fuolbull.cxx                       |    2 
 svx/sdi/svx.sdi                                      |   18 +++
 svx/source/dialog/svxbmpnumvalueset.cxx              |   26 ++++
 svx/source/sidebar/nbdtmg.cxx                        |   24 ++++
 svx/source/tbxctrls/bulletsnumbering.cxx             |  100 +++++++++++++++++--
 svx/uiconfig/ui/numberingwindow.ui                   |   69 ++++++++++++-
 sw/inc/doc.hxx                                       |    1 
 sw/inc/editsh.hxx                                    |    1 
 sw/qa/uitest/writer_tests2/formatBulletsNumbering.py |    7 +
 sw/sdi/_textsh.sdi                                   |    5 
 sw/source/core/doc/docnum.cxx                        |   23 ++++
 sw/source/core/edit/ednumber.cxx                     |    5 
 sw/source/uibase/shells/textsh1.cxx                  |   10 +
 sw/source/uibase/shells/txtnum.cxx                   |   18 ++-
 17 files changed, 310 insertions(+), 16 deletions(-)

New commits:
commit 61b38f766f14255297ec56d4e928dff40df21d92
Author:     Tibor Nagy <[email protected]>
AuthorDate: Sat May 18 23:31:56 2024 +0200
Commit:     Samuel Mehrbrodt <[email protected]>
CommitDate: Thu Jun 6 12:57:57 2024 +0200

    fix crash when push the Bullets button on the toolbar and then press the
    
    dropdown part of the button
    
    caused by commit I40cfc39501006146f7c6c04a1f3c7cf877c6f1c4
    (tdf#161056 Show bullets used in document in bullets dropdown)
    
    Change-Id: I215d7cb677825821917a4fd8c498deaaab9fc9b8
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167838
    Tested-by: Jenkins
    Reviewed-by: Nagy Tibor <[email protected]>
    (cherry picked from commit 708d619e32f251f06af8e8a057bf802627b81fbd)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168369
    Tested-by: allotropia jenkins <[email protected]>
    Reviewed-by: Samuel Mehrbrodt <[email protected]>

diff --git a/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py 
b/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py
index b3c5484964d4..abf090f7d16e 100644
--- a/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py
+++ b/sw/qa/uitest/writer_tests2/formatBulletsNumbering.py
@@ -259,4 +259,11 @@ class formatBulletsNumbering(UITestCase):
                 
self.assertEqual(get_state_as_dict(xselector)["SelectedItemId"], "73")
 
 
+   def test_bullets_and_numbering_document_bullet_list(self):
+        with self.ui_test.create_doc_in_start_center("writer"):
+            self.xUITest.executeCommand(".uno:DefaultBullet")
+            # Without the fix in place, this test would have crashed here
+            self.xUITest.executeCommand(".uno:DocumentBulletList")
+
+
 # vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx
index d571c3709c7d..afc6e7134b4b 100644
--- a/sw/source/core/doc/docnum.cxx
+++ b/sw/source/core/doc/docnum.cxx
@@ -2529,8 +2529,11 @@ std::vector<OUString> SwDoc::GetUsedBullets()
         for (int nLevel=0; nLevel<10; ++nLevel)
         {
             const SwNumFormat& rFormat = (*mpNumRuleTable)[nRule]->Get(nLevel);
-            if (SVX_NUM_CHAR_SPECIAL != rFormat.GetNumberingType())
+            if (SVX_NUM_CHAR_SPECIAL != rFormat.GetNumberingType()
+                || !rFormat.GetBulletFont().has_value())
+            {
                 continue;
+            }
             vcl::Font aFont(*rFormat.GetBulletFont());
             sal_UCS4 cBullet = rFormat.GetBulletChar();
             OUString sBullet(&cBullet, 1);
commit 240c0ffe5c2bfaebddbb97f0300c197b81b1a14e
Author:     Samuel Mehrbrodt <[email protected]>
AuthorDate: Mon May 6 09:20:58 2024 +0200
Commit:     Samuel Mehrbrodt <[email protected]>
CommitDate: Thu Jun 6 12:57:48 2024 +0200

    tdf#161056 Show bullets used in document in bullets dropdown
    
    Change-Id: I40cfc39501006146f7c6c04a1f3c7cf877c6f1c4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/167186
    Tested-by: Jenkins
    Reviewed-by: Samuel Mehrbrodt <[email protected]>
    (cherry picked from commit c8a5dc46d11f2ef1e3a66d633730d9a700ced24a)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168368
    Tested-by: allotropia jenkins <[email protected]>

diff --git a/include/svx/nbdtmg.hxx b/include/svx/nbdtmg.hxx
index 81ef80223496..9dfc1b16c67f 100644
--- a/include/svx/nbdtmg.hxx
+++ b/include/svx/nbdtmg.hxx
@@ -146,7 +146,7 @@ class SVX_DLLPUBLIC NBOTypeMgrBase
 };
 
 
-class BulletsTypeMgr final : public NBOTypeMgrBase
+class SVX_DLLPUBLIC BulletsTypeMgr final : public NBOTypeMgrBase
 {
     friend class OutlineTypeMgr;
     friend class NumberingTypeMgr;
@@ -162,6 +162,7 @@ class BulletsTypeMgr final : public NBOTypeMgrBase
         virtual sal_uInt16 GetNBOIndexForNumRule(SvxNumRule& aNum,sal_uInt16 
mLevel,sal_uInt16 nFromIndex=0) override;
         virtual void ReplaceNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, 
sal_uInt16 mLevel) override;
         virtual void ApplyNumRule(SvxNumRule& aNum, sal_uInt16 nIndex, 
sal_uInt16 mLevel, bool isDefault=false,bool isResetSize=false) override;
+        void ApplyCustomRule(SvxNumRule& aNum, std::u16string_view sBullet, 
std::u16string_view sFont, sal_uInt16 mLevel,bool isResetSize=false);
         virtual OUString GetDescription(sal_uInt16 nIndex, bool isDefault) 
override;
         virtual bool IsCustomized(sal_uInt16 nIndex) override;
         static BulletsTypeMgr& GetInstance();
diff --git a/include/svx/numvset.hxx b/include/svx/numvset.hxx
index 059d6b7bc558..d3b6e71a69e1 100644
--- a/include/svx/numvset.hxx
+++ b/include/svx/numvset.hxx
@@ -40,6 +40,7 @@ namespace com::sun::star {
 
 enum class NumberingPageType
 {
+    DOCBULLET,
     BULLET,
     SINGLENUM,
     OUTLINE,
@@ -55,6 +56,9 @@ class SVX_DLLPUBLIC SvxNumValueSet : public ValueSet
     css::uno::Reference<css::text::XNumberingFormatter> xFormatter;
     css::lang::Locale aLocale;
 
+    // Pair of bullet chars (first), and their respective font (second)
+    std::vector<std::pair<OUString, OUString>> maCustomBullets;
+
     css::uno::Sequence<
         css::uno::Sequence<
             css::beans::PropertyValue> > aNumSettings;
@@ -82,6 +86,9 @@ public:
             css::uno::Reference<css::text::XNumberingFormatter> const & 
xFormatter,
             const css::lang::Locale& rLocale);
 
+    std::vector<std::pair<OUString, OUString>> GetCustomBullets() { return 
maCustomBullets; }
+    void SetCustomBullets(std::vector<std::pair<OUString, OUString>> 
aCustomBullets);
+
     virtual FactoryFunction GetUITestFactory() const override;
 
 };
diff --git a/include/svx/svxids.hrc b/include/svx/svxids.hrc
index 7cc55ac02813..11470d0c673e 100644
--- a/include/svx/svxids.hrc
+++ b/include/svx/svxids.hrc
@@ -185,6 +185,7 @@ class XFillGradientItem;
 #define FN_BUL_NUM_RULE_INDEX   TypedWhichId<SfxUInt16Item>(FN_EDIT + 120) // 
achieving num rule index
 #define FN_NUM_NUM_RULE_INDEX   TypedWhichId<SfxUInt16Item>(FN_EDIT + 121)
 #define FN_OUTLINE_RULE_INDEX   TypedWhichId<SfxUInt16Item>(FN_EDIT + 122)
+#define FN_BUL_GET_DOC_BULLETS  TypedWhichId<SfxStringListItem>(FN_EDIT + 123)
 
 #define FN_INSERT               (SID_SW_START +  300) // 20300
 #define FN_DELETE_BOOKMARK      TypedWhichId<SfxStringItem>(FN_INSERT + 1)
@@ -1058,8 +1059,12 @@ class XFillGradientItem;
 #define SID_CHAR_DLG_FOR_PARAGRAPH                      ( SID_SVX_START + 1210 
)
 #define SID_SET_DOCUMENT_LANGUAGE                       
TypedWhichId<SfxBoolItem>( SID_SVX_START + 1211 )
 
+#define SID_ATTR_BULLET_CHAR                            
TypedWhichId<SfxStringItem>(SID_SVX_START + 1212)
+#define SID_ATTR_BULLET_FONT                            
TypedWhichId<SfxStringItem>(SID_SVX_START + 1213)
+#define SID_ATTR_BULLET_INDEX                           
TypedWhichId<SfxUInt16Item>(SID_SVX_START + 1214)
+
 // IMPORTANT NOTE: adjust SID_SVX_FIRSTFREE, when adding new slot id
-#define SID_SVX_FIRSTFREE                               ( SID_SVX_START + 1211 
+ 1 )
+#define SID_SVX_FIRSTFREE                               ( SID_SVX_START + 1214 
+ 1 )
 
 
 // Overflow check for slot IDs
diff --git a/sd/source/ui/func/fuolbull.cxx b/sd/source/ui/func/fuolbull.cxx
index 1f5a056b7ef7..ef9412956ece 100644
--- a/sd/source/ui/func/fuolbull.cxx
+++ b/sd/source/ui/func/fuolbull.cxx
@@ -123,7 +123,7 @@ void 
FuBulletAndPosition::SetCurrentBulletsNumbering(SfxRequest& rReq)
         return;
     }
 
-    const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nSId);
+    const SfxUInt16Item* pItem = 
rReq.GetArgs()->GetItem(SID_ATTR_BULLET_INDEX);
     if ( !pItem )
     {
         rReq.Done();
diff --git a/svx/sdi/svx.sdi b/svx/sdi/svx.sdi
index fad6109d6add..270d679cc04f 100644
--- a/svx/sdi/svx.sdi
+++ b/svx/sdi/svx.sdi
@@ -4991,6 +4991,21 @@ SfxUInt16Item CurrentNumListType FN_NUM_NUM_RULE_INDEX
     GroupId = SfxGroupId::Enumeration;
 ]
 
+SfxStringListItem DocumentBulletList FN_BUL_GET_DOC_BULLETS
+[
+    AutoUpdate = TRUE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = TRUE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = FALSE,
+    MenuConfig = FALSE,
+    ToolBoxConfig = FALSE,
+    GroupId = SfxGroupId::Enumeration;
+]
 
 SfxVoidItem InsertObject SID_INSERT_OBJECT
 ( SfxGlobalNameItem ClassId SID_INSERT_OBJECT )
@@ -6137,6 +6152,9 @@ SfxUInt16Item SetNumber FN_SVX_SET_NUMBER
 
 
 SfxUInt16Item SetBullet FN_SVX_SET_BULLET
+(SfxStringItem BulletChar SID_ATTR_BULLET_CHAR,
+ SfxStringItem BulletFont SID_ATTR_BULLET_FONT,
+ SfxUInt16Item BulletIndex SID_ATTR_BULLET_INDEX)
 [
     AutoUpdate = TRUE,
     FastCall = FALSE,
diff --git a/svx/source/dialog/svxbmpnumvalueset.cxx 
b/svx/source/dialog/svxbmpnumvalueset.cxx
index 17a39aad618f..a0c3761b13eb 100644
--- a/svx/source/dialog/svxbmpnumvalueset.cxx
+++ b/svx/source/dialog/svxbmpnumvalueset.cxx
@@ -149,13 +149,18 @@ void SvxNumValueSet::UserDraw( const UserDrawEvent& 
rUDEvt )
     aRuleFont.SetFillColor(aBackColor);
     css::uno::Sequence< OUString > aBulletSymbols;
 
-    if(ePageType == NumberingPageType::BULLET)
+    if(ePageType == NumberingPageType::BULLET || ePageType == 
NumberingPageType::DOCBULLET)
     {
         aBulletSymbols = 
officecfg::Office::Common::BulletsNumbering::DefaultBullets::get();
         css::uno::Sequence< OUString > 
aBulletFonts(officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get());
         aRuleFont.SetFamilyName(aBulletFonts[nIndex]);
         aFont = aRuleFont;
     }
+    else if (ePageType == NumberingPageType::DOCBULLET)
+    {
+        aRuleFont.SetFamilyName(maCustomBullets[nIndex].second);
+        aFont = aRuleFont;
+    }
     else if(ePageType == NumberingPageType::OUTLINE)
     {
         aSize.setHeight( nRectHeight/8 );
@@ -198,7 +203,8 @@ void SvxNumValueSet::UserDraw( const UserDrawEvent& rUDEvt )
     // Now comes the text
     static constexpr OUStringLiteral sValue(u"Value");
     if( NumberingPageType::SINGLENUM == ePageType ||
-           NumberingPageType::BULLET == ePageType )
+           NumberingPageType::BULLET == ePageType ||
+           NumberingPageType::DOCBULLET == ePageType)
     {
         Point aStart(aBLPos.X() + nRectWidth / 9,0);
         for( sal_uInt16 i = 0; i < 3; i++ )
@@ -212,6 +218,12 @@ void SvxNumValueSet::UserDraw( const UserDrawEvent& rUDEvt 
)
                 aStart.AdjustY( -(pDev->GetTextHeight()/2) );
                 aStart.setX( aBLPos.X() + 5 );
             }
+            else if (ePageType == NumberingPageType::DOCBULLET)
+            {
+                sText = maCustomBullets[nIndex].first;
+                aStart.AdjustY( -(pDev->GetTextHeight()/2) );
+                aStart.setX( aBLPos.X() + 5 );
+            }
             else
             {
                 if(xFormatter.is() && aNumSettings.getLength() > nIndex)
@@ -446,6 +458,16 @@ void SvxNumValueSet::SetOutlineNumberingSettings(
     }
 }
 
+void SvxNumValueSet::SetCustomBullets(std::vector<std::pair<OUString, 
OUString>> aCustomBullets)
+{
+    Clear();
+    maCustomBullets = aCustomBullets;
+    for (size_t i = 0; i < aCustomBullets.size(); i++)
+    {
+        InsertItem(i + 1, i);
+    }
+}
+
 SvxBmpNumValueSet::SvxBmpNumValueSet(std::unique_ptr<weld::ScrolledWindow> 
pScrolledWindow)
     : SvxNumValueSet(std::move(pScrolledWindow))
     , aFormatIdle("SvxBmpNumValueSet FormatIdle")
diff --git a/svx/source/sidebar/nbdtmg.cxx b/svx/source/sidebar/nbdtmg.cxx
index f26301d54a76..dca5e176e571 100644
--- a/svx/source/sidebar/nbdtmg.cxx
+++ b/svx/source/sidebar/nbdtmg.cxx
@@ -342,6 +342,30 @@ void BulletsTypeMgr::ApplyNumRule(SvxNumRule& aNum, 
sal_uInt16 nIndex, sal_uInt1
     }
 }
 
+void BulletsTypeMgr::ApplyCustomRule(SvxNumRule& aNum, std::u16string_view 
sBullet,
+                                     std::u16string_view sFont, sal_uInt16 
mLevel, bool isResetSize)
+{
+    sal_uInt16 nMask = 1;
+    OUString sBulletCharFormatName = GetBulletCharFmtName();
+    const vcl::Font aFont(OUString(sFont), Size(1, 1));
+    for (sal_uInt16 i = 0; i < aNum.GetLevelCount(); i++)
+    {
+        if (mLevel & nMask)
+        {
+            SvxNumberFormat aFmt(aNum.GetLevel(i));
+            aFmt.SetNumberingType(SVX_NUM_CHAR_SPECIAL);
+            aFmt.SetBulletFont(&aFont);
+            aFmt.SetBulletChar(sBullet[0]);
+            aFmt.SetCharFormatName(sBulletCharFormatName);
+            aFmt.SetListFormat("");
+            if (isResetSize)
+                aFmt.SetBulletRelSize(45);
+            aNum.SetLevel(i, aFmt);
+        }
+        nMask <<= 1;
+    }
+}
+
 OUString BulletsTypeMgr::GetDescription(sal_uInt16 nIndex, bool /*isDefault*/)
 {
     OUString sRet;
diff --git a/svx/source/tbxctrls/bulletsnumbering.cxx 
b/svx/source/tbxctrls/bulletsnumbering.cxx
index e1a55a112346..78ec7601d5aa 100644
--- a/svx/source/tbxctrls/bulletsnumbering.cxx
+++ b/svx/source/tbxctrls/bulletsnumbering.cxx
@@ -9,9 +9,11 @@
 
 #include <com/sun/star/text/DefaultNumberingProvider.hpp>
 #include <com/sun/star/text/XNumberingFormatter.hpp>
+#include <com/sun/star/uno/Sequence.hxx>
 
 #include <comphelper/propertysequence.hxx>
 #include <i18nlangtag/languagetag.hxx>
+#include <officecfg/Office/Common.hxx>
 #include <svtools/popupwindowcontroller.hxx>
 #include <svtools/toolbarmenu.hxx>
 #include <svx/strings.hrc>
@@ -32,8 +34,13 @@ class NumberingPopup : public WeldToolbarPopup
     NumberingToolBoxControl& mrController;
     std::unique_ptr<SvxNumValueSet> mxValueSet;
     std::unique_ptr<weld::CustomWeld> mxValueSetWin;
+    std::unique_ptr<SvxNumValueSet> mxValueSetDoc;
+    std::unique_ptr<weld::CustomWeld> mxValueSetWinDoc;
     std::unique_ptr<weld::Button> mxMoreButton;
+    std::unique_ptr<weld::Label> mxBulletsLabel;
+    std::unique_ptr<weld::Label> mxDocBulletsLabel;
     DECL_LINK(VSSelectValueSetHdl, ValueSet*, void);
+    DECL_LINK(VSSelectValueSetDocHdl, ValueSet*, void);
     DECL_LINK(VSButtonClickSetHdl, weld::Button&, void);
 
     virtual void GrabFocus() override;
@@ -70,13 +77,22 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& 
rController,
     , mrController(rController)
     , mxValueSet(new 
SvxNumValueSet(m_xBuilder->weld_scrolled_window("valuesetwin", true)))
     , mxValueSetWin(new weld::CustomWeld(*m_xBuilder, "valueset", *mxValueSet))
+    , mxValueSetDoc(new 
SvxNumValueSet(m_xBuilder->weld_scrolled_window(u"valuesetwin_doc"_ustr, true)))
+    , mxValueSetWinDoc(new weld::CustomWeld(*m_xBuilder, u"valueset_doc"_ustr, 
*mxValueSetDoc))
     , mxMoreButton(m_xBuilder->weld_button("more"))
+    , mxBulletsLabel(m_xBuilder->weld_label(u"label_default"_ustr))
+    , mxDocBulletsLabel(m_xBuilder->weld_label(u"label_doc"_ustr))
 {
     mxValueSet->SetStyle(WB_MENUSTYLEVALUESET | WB_FLATVALUESET | 
WB_NO_DIRECTSELECT);
+    mxValueSetDoc->SetStyle(WB_MENUSTYLEVALUESET | WB_FLATVALUESET | 
WB_NO_DIRECTSELECT);
     mxValueSet->init(mePageType);
+    mxValueSetDoc->init(NumberingPageType::DOCBULLET);
+    mxValueSetWinDoc->hide();
+    mxDocBulletsLabel->hide();
 
     if ( mePageType != NumberingPageType::BULLET )
     {
+        mxBulletsLabel->hide();
         css::uno::Reference< css::text::XDefaultNumberingProvider > xDefNum = 
css::text::DefaultNumberingProvider::create( mrController.getContext() );
         if ( xDefNum.is() )
         {
@@ -99,17 +115,25 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& 
rController,
     }
 
     weld::DrawingArea* pDrawingArea = mxValueSet->GetDrawingArea();
+    weld::DrawingArea* pDrawingAreaDoc = mxValueSetDoc->GetDrawingArea();
     OutputDevice& rRefDevice = pDrawingArea->get_ref_device();
     Size aItemSize(rRefDevice.LogicToPixel(Size(30, 42), 
MapMode(MapUnit::MapAppFont)));
     mxValueSet->SetExtraSpacing( 2 );
+    mxValueSetDoc->SetExtraSpacing( 2 );
     Size aSize(mxValueSet->CalcWindowSizePixel(aItemSize));
     pDrawingArea->set_size_request(aSize.Width(), aSize.Height());
+    pDrawingAreaDoc->set_size_request(aSize.Width(), aSize.Height());
     mxValueSet->SetOutputSizePixel(aSize);
+    mxValueSetDoc->SetOutputSizePixel(aSize);
     
mxValueSet->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor());
+    
mxValueSetDoc->SetColor(Application::GetSettings().GetStyleSettings().GetFieldColor());
 
     OUString aMoreItemText = SvxResId( RID_SVXSTR_CUSTOMIZE );
     if ( mePageType == NumberingPageType::BULLET )
+    {
         AddStatusListener( ".uno:CurrentBulletListType" );
+        AddStatusListener( ".uno:DocumentBulletList" );
+    }
     else if ( mePageType == NumberingPageType::SINGLENUM )
         AddStatusListener( ".uno:CurrentNumListType" );
     else
@@ -121,15 +145,67 @@ NumberingPopup::NumberingPopup(NumberingToolBoxControl& 
rController,
     mxMoreButton->connect_clicked(LINK(this, NumberingPopup, 
VSButtonClickSetHdl));
 
     mxValueSet->SetSelectHdl(LINK(this, NumberingPopup, VSSelectValueSetHdl));
+    mxValueSetDoc->SetSelectHdl(LINK(this, NumberingPopup, 
VSSelectValueSetDocHdl));
 }
 
-void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& 
rEvent )
+namespace
+{
+bool lcl_BulletIsDefault(std::u16string_view aSymbol, std::u16string_view 
aFont)
 {
-    mxValueSet->SetNoSelection();
+    css::uno::Sequence<OUString> aBulletSymbols
+        = officecfg::Office::Common::BulletsNumbering::DefaultBullets::get();
+    css::uno::Sequence<OUString> aBulletFonts
+        = 
officecfg::Office::Common::BulletsNumbering::DefaultBulletsFonts::get();
+    for (sal_Int32 i = 0; i < aBulletSymbols.getLength(); i++)
+    {
+        if (aBulletSymbols[i] == aSymbol && aBulletFonts[i] == aFont)
+            return true;
+    }
+    return false;
+}
+}
 
-    sal_Int32 nSelItem;
-    if ( rEvent.State >>= nSelItem )
-        mxValueSet->SelectItem( nSelItem );
+void NumberingPopup::statusChanged( const css::frame::FeatureStateEvent& 
rEvent )
+{
+    if (rEvent.FeatureURL.Complete == ".uno:DocumentBulletList")
+    {
+        css::uno::Sequence<OUString> aSeq;
+        if (rEvent.State >>= aSeq)
+        {
+            std::vector<std::pair<OUString, OUString>> aList;
+            mxValueSetDoc->Clear();
+            int i = 1;
+            // The string contains the bullet as first character, and then the 
font name
+            for (const OUString& sBulletFont : aSeq)
+            {
+                OUString sBullet(sBulletFont.copy(0, 1));
+                OUString sFont(sBulletFont.copy(1, sBulletFont.getLength() - 
1));
+                if (lcl_BulletIsDefault(sBullet, sFont))
+                    continue;
+                mxValueSetDoc->InsertItem(i, sBullet, i);
+                aList.emplace_back(sBullet, sFont);
+                i++;
+            }
+            if (!aList.empty())
+            {
+                mxValueSetWinDoc->show();
+                mxDocBulletsLabel->show();
+                mxValueSetDoc->SetCustomBullets(aList);
+            }
+            else
+            {
+                mxValueSetWinDoc->hide();
+                mxDocBulletsLabel->hide();
+            }
+        }
+    }
+    else
+    {
+        mxValueSet->SetNoSelection();
+        sal_Int32 nSelItem;
+        if ( rEvent.State >>= nSelItem )
+            mxValueSet->SelectItem( nSelItem );
+    }
 }
 
 IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, ValueSet*, void)
@@ -137,7 +213,7 @@ IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, 
ValueSet*, void)
     sal_uInt16 nSelItem = mxValueSet->GetSelectedItemId();
     if ( mePageType == NumberingPageType::BULLET )
     {
-        auto aArgs( comphelper::InitPropertySequence( { { "SetBullet", 
css::uno::Any( nSelItem ) } } ) );
+        auto aArgs( comphelper::InitPropertySequence( { { "BulletIndex", 
css::uno::Any( nSelItem ) } } ) );
         mrController.dispatchCommand( ".uno:SetBullet", aArgs );
     }
     else if ( mePageType == NumberingPageType::SINGLENUM )
@@ -153,6 +229,18 @@ IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetHdl, 
ValueSet*, void)
     mrController.EndPopupMode();
 }
 
+IMPL_LINK_NOARG(NumberingPopup, VSSelectValueSetDocHdl, ValueSet*, void)
+{
+    sal_uInt16 nSelItem = mxValueSetDoc->GetSelectedItemId() - 1;
+    auto aCustomBullets = mxValueSetDoc->GetCustomBullets();
+    OUString nChar(aCustomBullets[nSelItem].first);
+    OUString sFont(aCustomBullets[nSelItem].second);
+    auto aArgs(comphelper::InitPropertySequence(
+        { { "BulletChar", css::uno::Any(nChar) }, { "BulletFont", 
css::uno::Any(sFont) } }));
+    mrController.dispatchCommand(".uno:SetBullet", aArgs);
+    mrController.EndPopupMode();
+}
+
 void NumberingPopup::GrabFocus()
 {
     mxValueSet->GrabFocus();
diff --git a/svx/uiconfig/ui/numberingwindow.ui 
b/svx/uiconfig/ui/numberingwindow.ui
index e303830fc01e..af5bcadf96ff 100644
--- a/svx/uiconfig/ui/numberingwindow.ui
+++ b/svx/uiconfig/ui/numberingwindow.ui
@@ -18,6 +18,21 @@
         <property name="can-focus">False</property>
         <property name="orientation">vertical</property>
         <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label_default">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes" 
context="numberingwindow|label_default">Bullet Library</property>
+            <accessibility>
+              <relation type="label-for" target="valueset"/>
+            </accessibility>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkScrolledWindow" id="valuesetwin">
             <property name="visible">True</property>
@@ -38,6 +53,9 @@
                     <property name="events">GDK_BUTTON_PRESS_MASK | 
GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | 
GDK_STRUCTURE_MASK</property>
                     <property name="hexpand">True</property>
                     <property name="vexpand">True</property>
+                    <accessibility>
+                      <relation type="labelled-by" target="label_default"/>
+                    </accessibility>
                   </object>
                 </child>
               </object>
@@ -49,6 +67,55 @@
             <property name="position">1</property>
           </packing>
         </child>
+        <child>
+          <object class="GtkLabel" id="label_doc">
+            <property name="visible">True</property>
+            <property name="can-focus">False</property>
+            <property name="label" translatable="yes" 
context="numberingwindow|label_doc">Document Bullets</property>
+            <accessibility>
+              <relation type="label-for" target="valueset_doc"/>
+            </accessibility>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="valuesetwin_doc">
+            <property name="visible">True</property>
+            <property name="can-focus">True</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="hscrollbar-policy">never</property>
+            <property name="vscrollbar-policy">never</property>
+            <property name="shadow-type">in</property>
+            <child>
+              <object class="GtkViewport">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <child>
+                  <object class="GtkDrawingArea" id="valueset_doc">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="events">GDK_BUTTON_PRESS_MASK | 
GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK | 
GDK_STRUCTURE_MASK</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <accessibility>
+                      <relation type="labelled-by" target="label_doc"/>
+                    </accessibility>
+                  </object>
+                </child>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">3</property>
+          </packing>
+        </child>
         <child>
           <object class="GtkButton" id="more">
             <property name="visible">True</property>
@@ -61,7 +128,7 @@
           <packing>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="position">2</property>
+            <property name="position">4</property>
           </packing>
         </child>
       </object>
diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx
index 946c96fd29db..8f530d8646fa 100644
--- a/sw/inc/doc.hxx
+++ b/sw/inc/doc.hxx
@@ -1103,6 +1103,7 @@ public:
             SvxNumberFormat::LABEL_WIDTH_AND_POSITION );
     sal_uInt16 FindNumRule( std::u16string_view rName ) const;
     SwNumRule* FindNumRulePtr( const OUString& rName ) const;
+    std::vector<OUString> GetUsedBullets();
 
     // Deletion only possible if Rule is not used!
     bool RenameNumRule(const OUString & aOldName, const OUString & aNewName,
diff --git a/sw/inc/editsh.hxx b/sw/inc/editsh.hxx
index 2b753530159a..96433ea89955 100644
--- a/sw/inc/editsh.hxx
+++ b/sw/inc/editsh.hxx
@@ -578,6 +578,7 @@ public:
      text node belongs, which applies the found list style. */
     const SwNumRule * SearchNumRule(const bool bNum,
                                     OUString& sListId );
+    std::vector<OUString> GetUsedBullets();
 
     /** Undo.
      Maintain UndoHistory in Document.
diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi
index e5a4bfd0ad54..4c5a48b7d697 100644
--- a/sw/sdi/_textsh.sdi
+++ b/sw/sdi/_textsh.sdi
@@ -810,6 +810,11 @@ interface BaseText
         StateMethod = GetState ;
         DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
     ]
+    FN_BUL_GET_DOC_BULLETS // status(final|play)
+    [
+        StateMethod = GetState ;
+        DisableFlags="SfxDisableFlags::SwOnProtectedCursor";
+    ]
     FN_NUMBER_BULLETS // status(final|play)
     [
         ExecMethod = ExecEnterNum ;
diff --git a/sw/source/core/doc/docnum.cxx b/sw/source/core/doc/docnum.cxx
index 01c4a1b3874a..d571c3709c7d 100644
--- a/sw/source/core/doc/docnum.cxx
+++ b/sw/source/core/doc/docnum.cxx
@@ -2521,6 +2521,26 @@ sal_uInt16 SwDoc::FindNumRule( std::u16string_view rName 
) const
     return USHRT_MAX;
 }
 
+std::vector<OUString> SwDoc::GetUsedBullets()
+{
+    std::vector<OUString> aUsedBullets;
+    for (size_t nRule = 0; nRule < mpNumRuleTable->size(); ++nRule)
+    {
+        for (int nLevel=0; nLevel<10; ++nLevel)
+        {
+            const SwNumFormat& rFormat = (*mpNumRuleTable)[nRule]->Get(nLevel);
+            if (SVX_NUM_CHAR_SPECIAL != rFormat.GetNumberingType())
+                continue;
+            vcl::Font aFont(*rFormat.GetBulletFont());
+            sal_UCS4 cBullet = rFormat.GetBulletChar();
+            OUString sBullet(&cBullet, 1);
+            OUString sFontName(aFont.GetFamilyName());
+            aUsedBullets.emplace_back(sBullet + sFontName);
+        }
+    }
+    return aUsedBullets;
+}
+
 SwNumRule* SwDoc::FindNumRulePtr( const OUString& rName ) const
 {
     SwNumRule * pResult = maNumRuleMap[rName];
diff --git a/sw/source/core/edit/ednumber.cxx b/sw/source/core/edit/ednumber.cxx
index 65391d376b4a..7217b7fbd989 100644
--- a/sw/source/core/edit/ednumber.cxx
+++ b/sw/source/core/edit/ednumber.cxx
@@ -879,4 +879,9 @@ const SwNumRule * SwEditShell::SearchNumRule( const bool 
bNum,
                                     sListId, GetLayout() );
 }
 
+std::vector<OUString> SwEditShell::GetUsedBullets()
+{
+    return GetDoc()->GetUsedBullets();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/shells/textsh1.cxx 
b/sw/source/uibase/shells/textsh1.cxx
index 2bf6c670e489..4f452a8add37 100644
--- a/sw/source/uibase/shells/textsh1.cxx
+++ b/sw/source/uibase/shells/textsh1.cxx
@@ -2733,6 +2733,16 @@ void SwTextShell::GetState( SfxItemSet &rSet )
                 }
             }
         }
+            break;
+            case FN_BUL_GET_DOC_BULLETS:
+            {
+                std::vector<OUString> aBullets = rSh.GetUsedBullets();
+                SfxStringListItem aItem(FN_BUL_GET_DOC_BULLETS);
+                uno::Sequence<OUString> aSeq(aBullets.data(),
+                                             
static_cast<sal_Int32>(aBullets.size()));
+                aItem.SetStringList(aSeq);
+                rSet.Put(aItem);
+            }
             break;
             case FN_NUM_CONTINUE:
             {
diff --git a/sw/source/uibase/shells/txtnum.cxx 
b/sw/source/uibase/shells/txtnum.cxx
index e769b7f46347..43c1b8d1aedd 100644
--- a/sw/source/uibase/shells/txtnum.cxx
+++ b/sw/source/uibase/shells/txtnum.cxx
@@ -261,10 +261,12 @@ void SwTextShell::ExecSetNumber(SfxRequest const &rReq)
     case FN_SVX_SET_BULLET:
     case FN_SVX_SET_OUTLINE:
         {
-            const SfxUInt16Item* pItem = rReq.GetArg<SfxUInt16Item>(nSlot);
-            if ( pItem != nullptr )
+            const SfxUInt16Item* pIndexItem = rReq.GetArgs()->GetItem( 
SID_ATTR_BULLET_INDEX );
+            const SfxStringItem* pCharItem = rReq.GetArgs()->GetItem( 
SID_ATTR_BULLET_CHAR );
+            const SfxStringItem* pFontItem = rReq.GetArgs()->GetItem( 
SID_ATTR_BULLET_FONT );
+
+            if ( pIndexItem != nullptr || ( pCharItem != nullptr && pFontItem 
!= nullptr ) )
             {
-                const sal_uInt16 nChosenItemIdx = pItem->GetValue();
                 svx::sidebar::NBOType nNBOType = 
svx::sidebar::NBOType::Bullets;
                 if ( nSlot == FN_SVX_SET_NUMBER )
                     nNBOType = svx::sidebar::NBOType::Numbering;
@@ -302,7 +304,15 @@ void SwTextShell::ExecSetNumber(SfxRequest const &rReq)
                     aSet.Put( SvxNumBulletItem( aNewSvxNumRule, 
SID_ATTR_NUMBERING_RULE ) );
 
                     pNBOTypeMgr->SetItems( &aSet );
-                    pNBOTypeMgr->ApplyNumRule( aNewSvxNumRule, nChosenItemIdx 
- 1, nActNumLvl );
+                    if (pIndexItem)
+                        pNBOTypeMgr->ApplyNumRule( aNewSvxNumRule, 
pIndexItem->GetValue() - 1, nActNumLvl );
+                    else
+                    {
+                        svx::sidebar::BulletsTypeMgr* pBulletsTypeMgr
+                            = 
dynamic_cast<svx::sidebar::BulletsTypeMgr*>(pNBOTypeMgr);
+                        pBulletsTypeMgr->ApplyCustomRule(aNewSvxNumRule, 
pCharItem->GetValue(),
+                                                         
pFontItem->GetValue(), nActNumLvl);
+                    }
 
                     aNewNumRule.SetSvxRule( aNewSvxNumRule, 
GetShell().GetDoc() );
                     aNewNumRule.SetAutoRule( true );

Reply via email to