desktop/source/lib/init.cxx                                          |  187 
+++++-----
 include/LibreOfficeKit/LibreOfficeKit.h                              |    1 
 include/LibreOfficeKit/LibreOfficeKit.hxx                            |    3 
 include/vcl/ITiledRenderable.hxx                                     |    1 
 linguistic/source/gciterator.cxx                                     |    7 
 officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu |    8 
 sd/qa/unit/tiledrendering/tiledrendering.cxx                         |   15 
 sd/source/ui/inc/unomodel.hxx                                        |    1 
 sd/source/ui/unoidl/unomodel.cxx                                     |   26 +
 sfx2/source/control/dispatch.cxx                                     |    1 
 sfx2/source/control/unoctitm.cxx                                     |    2 
 sw/inc/AnnotationWin.hxx                                             |    3 
 sw/inc/PostItMgr.hxx                                                 |    2 
 sw/inc/cmdid.h                                                       |    1 
 sw/sdi/_annotsh.sdi                                                  |    6 
 sw/sdi/_textsh.sdi                                                   |    5 
 sw/sdi/swriter.sdi                                                   |   17 
 sw/source/uibase/docvw/AnnotationMenuButton.cxx                      |    4 
 sw/source/uibase/docvw/AnnotationWin.cxx                             |   18 
 sw/source/uibase/docvw/AnnotationWin2.cxx                            |   12 
 sw/source/uibase/docvw/PostItMgr.cxx                                 |   56 ++
 sw/source/uibase/shells/annotsh.cxx                                  |   10 
 sw/source/uibase/shells/textfld.cxx                                  |   21 -
 sw/source/uibase/uno/unotxdoc.cxx                                    |    8 
 sw/uiconfig/sglobal/menubar/menubar.xml                              |    1 
 sw/uiconfig/sglobal/popupmenu/annotation.xml                         |    1 
 sw/uiconfig/swriter/menubar/menubar.xml                              |    1 
 sw/uiconfig/swriter/popupmenu/annotation.xml                         |    1 
 sw/uiconfig/swriter/ui/annotation.ui                                 |    8 
 sw/uiconfig/swriter/ui/notebookbar_groupedbar_full.ui                |    7 
 xmlsecurity/inc/digitalsignaturesdialog.hxx                          |    2 
 xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx               |   57 +--
 32 files changed, 360 insertions(+), 133 deletions(-)

New commits:
commit fd88a5bcb271a1711f484a319ee23d6b7013b232
Author:     Caolán McNamara <[email protected]>
AuthorDate: Tue Sep 17 14:10:27 2024 +0100
Commit:     Michael Meeks <[email protected]>
CommitDate: Tue Sep 17 16:06:05 2024 +0200

    reset m_bEnd after use to quit lcl_workerfunc
    
    so lcl_workerfunc can be launched again on-demand
    
    Change-Id: I23dd48dc433190413f5c63464dcce112128b81ad
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173564
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Michael Meeks <[email protected]>

diff --git a/linguistic/source/gciterator.cxx b/linguistic/source/gciterator.cxx
index ad85bab95953..7505ad634c98 100644
--- a/linguistic/source/gciterator.cxx
+++ b/linguistic/source/gciterator.cxx
@@ -310,9 +310,14 @@ void GrammarCheckingIterator::TerminateThread()
         osl_joinWithThread(t);
         osl_destroyThread(t);
     }
+    // After m_bEnd was used to flag lcl_workerfunc to quit, now
+    // reset it so lcl_workerfunc could be relaunched later.
+    {
+        ::osl::Guard< ::osl::Mutex > aGuard( MyMutex() );
+        m_bEnd = false;
+    }
 }
 
-
 bool GrammarCheckingIterator::joinThreads()
 {
     TerminateThread();
commit 3fa8df9e7f46fd7bf988ca96b0454e5c1ee0a153
Author:     Pranam Lashkari <[email protected]>
AuthorDate: Mon Sep 16 21:02:22 2024 +0300
Commit:     Caolán McNamara <[email protected]>
CommitDate: Tue Sep 17 12:30:01 2024 +0200

    LOK: send state of EditDoc for write protection status
    
    Change-Id: I58eb4ab04b4063e382bc6550b5cf08d7806a6c6a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173470
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 4ee7c0fcc8a1..d1f7603d8d05 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -4125,6 +4125,7 @@ static void doc_iniUnoCommands ()
         u".uno:DistributeVertTop"_ustr,
         u".uno:AnimationEffects"_ustr,
         u".uno:ExecuteAnimationEffect"_ustr,
+        u".uno:EditDoc"_ustr,
     };
 
     util::URL aCommandURL;
diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx
index 720062c8b3cb..e898f565f8ff 100644
--- a/sfx2/source/control/unoctitm.cxx
+++ b/sfx2/source/control/unoctitm.cxx
@@ -1152,6 +1152,7 @@ constexpr auto handlers = 
frozen::make_unordered_map<std::u16string_view, Payloa
     { u"NormalMultiPaneGUI", IsActivePayload },
     { u"NotesMode", IsActivePayload },
     { u"SlideMasterPage", IsActivePayload },
+    { u"EditDoc", IsActivePayload },
 
     { u"CharFontName", FontNamePayload },
 
commit b851cb61d3e4d5018475051f785d7659694a21e8
Author:     Caolán McNamara <[email protected]>
AuthorDate: Mon Sep 16 17:33:44 2024 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Sep 17 10:54:36 2024 +0200

    This should iterate over the thesaurus languages, not the spelling ones
    
    Change-Id: I94410274f7afbc0a6bc33fe43beb9810a905dfe4
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173467
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index fbc0da6d3262..4ee7c0fcc8a1 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -7971,7 +7971,7 @@ static void preloadData()
 
     // preload all available thesauri
     css::uno::Reference<linguistic2::XThesaurus> 
xThesaurus(xLngSvcMgr->getThesaurus());
-    css::uno::Reference<linguistic2::XSupportedLocales> 
xThesLocales(xSpellChecker, css::uno::UNO_QUERY_THROW);
+    css::uno::Reference<linguistic2::XSupportedLocales> 
xThesLocales(xThesaurus, css::uno::UNO_QUERY_THROW);
     aLocales = xThesLocales->getLocales();
     std::cerr << "Preloading local thesauri: ";
     for (auto &it : std::as_const(aLocales))
commit e20ed8010492fca809f9a3fc9523c092404af0e0
Author:     Miklos Vajna <[email protected]>
AuthorDate: Mon Sep 16 08:18:36 2024 +0200
Commit:     Caolán McNamara <[email protected]>
CommitDate: Tue Sep 17 10:01:04 2024 +0200

    cool#9992 lok doc sign: implement signature removal
    
    Open an already signed document, click on the sign icon on the status
    bar, notice how the button to remove a signature is hidden.
    
    This was added in commit 71a8bad4b96627fd965b23288dea14aae3f0f468
    (jsdialog: enable Digital Signatures dialog, 2022-01-24), which exposed
    the signatures dialog as a read-only jsdialog. The dialog was improved
    recently to be a read-write jsdialog, so this is no longer needed.
    
    But then DigitalSignaturesDialog::canRemove() had an inner non-async
    message dialog. Fix that by converting canRemove() to async.
    
    An additional problem could be that the document is not marked as
    modified, so the LOK client code doesn't notice the document is updated
    (to not have a signature), but we do update the last mod timestamp of
    the file, which is meant to be enough.
    
    (cherry picked from commit 40ba7a5c25f0d2ea90a976d4e7d56b9e61dbedd1)
    
    Change-Id: I8e7ee22e4b1b8ce59dee3617bb2f22f8d734f31d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173515
    Reviewed-by: Caolán McNamara <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/xmlsecurity/inc/digitalsignaturesdialog.hxx 
b/xmlsecurity/inc/digitalsignaturesdialog.hxx
index 375328d91a88..0b6c544c8e3c 100644
--- a/xmlsecurity/inc/digitalsignaturesdialog.hxx
+++ b/xmlsecurity/inc/digitalsignaturesdialog.hxx
@@ -97,7 +97,7 @@ private:
     //See the spec at 
specs/www/appwide/security/Electronic_Signatures_and_Security.sxw
     //(6.6.2)Behaviour with regard to ODF 1.2
     bool canAdd();
-    bool canRemove();
+    void canRemove(const std::function<void(bool)>& rCallback);
 
     bool canAddRemove();
 
diff --git a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx 
b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
index 6fef60f01194..82d50891b674 100644
--- a/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
+++ b/xmlsecurity/source/dialogs/digitalsignaturesdialog.cxx
@@ -307,7 +307,6 @@ DigitalSignaturesDialog::DigitalSignaturesDialog(
     if (comphelper::LibreOfficeKit::isActive())
     {
         m_xAddBtn->hide();
-        m_xRemoveBtn->hide();
         m_xStartCertMgrBtn->hide();
     }
 
@@ -439,20 +438,25 @@ bool DigitalSignaturesDialog::canAddRemove()
 
 bool DigitalSignaturesDialog::canAdd() { return canAddRemove(); }
 
-bool DigitalSignaturesDialog::canRemove()
+void DigitalSignaturesDialog::canRemove(const std::function<void(bool)>& 
rCallback)
 {
+    auto onFinished = [this, rCallback](bool bRet) {
+        rCallback(bRet && canAddRemove());
+    };
     bool bRet = true;
 
     if ( maSignatureManager.getSignatureMode() == 
DocumentSignatureMode::Content )
     {
-        std::unique_ptr<weld::MessageDialog> 
xBox(Application::CreateMessageDialog(m_xDialog.get(),
+        std::shared_ptr<weld::MessageDialog> 
xBox(Application::CreateMessageDialog(m_xDialog.get(),
                                                   VclMessageType::Question, 
VclButtonsType::YesNo,
                                                   
XsResId(STR_XMLSECDLG_QUERY_REALLYREMOVE)));
-        short nDlgRet = xBox->run();
-        bRet = ( nDlgRet == RET_YES );
+        xBox->runAsync(xBox, [onFinished](sal_Int32 nDlgRet) {
+                onFinished(nDlgRet == RET_YES);
+        });
+        return;
     }
 
-    return (bRet && canAddRemove());
+    onFinished(bRet);
 }
 
 void DigitalSignaturesDialog::beforeRun()
@@ -590,28 +594,31 @@ IMPL_LINK_NOARG(DigitalSignaturesDialog, AddButtonHdl, 
weld::Button&, void)
 
 IMPL_LINK_NOARG(DigitalSignaturesDialog, RemoveButtonHdl, weld::Button&, void)
 {
-    if (!canRemove())
-        return;
-    int nEntry = m_xSignaturesLB->get_selected_index();
-    if (nEntry == -1)
-        return;
+    canRemove([this](bool bRet) {
+        if (!bRet)
+            return;
 
-    try
-    {
-        sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
-        maSignatureManager.remove(nSelected);
+        int nEntry = m_xSignaturesLB->get_selected_index();
+        if (nEntry == -1)
+            return;
 
-        mbSignaturesChanged = true;
+        try
+        {
+            sal_uInt16 nSelected = m_xSignaturesLB->get_id(nEntry).toUInt32();
+            maSignatureManager.remove(nSelected);
 
-        ImplFillSignaturesBox();
-    }
-    catch ( uno::Exception& )
-    {
-        TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "Exception while removing 
a signature!" );
-        // Don't keep invalid entries...
-        ImplGetSignatureInformations(/*bUseTempStream=*/true, 
/*bCacheLastSignature=*/true);
-        ImplFillSignaturesBox();
-    }
+            mbSignaturesChanged = true;
+
+            ImplFillSignaturesBox();
+        }
+        catch ( uno::Exception& )
+        {
+            TOOLS_WARN_EXCEPTION( "xmlsecurity.dialogs", "Exception while 
removing a signature!" );
+            // Don't keep invalid entries...
+            ImplGetSignatureInformations(/*bUseTempStream=*/true, 
/*bCacheLastSignature=*/true);
+            ImplFillSignaturesBox();
+        }
+    });
 }
 
 
commit c5fc86e770901eb90356cb31d4ac71ac7dad9ce6
Author:     Caolán McNamara <[email protected]>
AuthorDate: Mon Sep 16 12:55:33 2024 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Sep 17 08:40:19 2024 +0200

    Output what languages are handled by LanguageTool
    
    to explain the absence of languages that are listed by 'Preloading'
    because the languages handled by a remote LanguageTool are removed
    from the languages handled with local data.
    
    Change-Id: I203657f68a7b9399e39ebf9ab9447c7ae56efe68
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173448
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 463ea4537987..fbc0da6d3262 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -1029,8 +1029,10 @@ void hideSidebar()
         SetLastExceptionMsg(u"No view shell or sidebar"_ustr);
 }
 
-void setLanguageToolConfig()
+css::uno::Sequence<css::lang::Locale> setLanguageToolConfig()
 {
+    css::uno::Sequence<css::lang::Locale> aLTLocales;
+
     const char* pEnabled = ::getenv("LANGUAGETOOL_ENABLED");
     const char* pBaseUrlString = ::getenv("LANGUAGETOOL_BASEURL");
 
@@ -1043,7 +1045,7 @@ void setLanguageToolConfig()
 
         OUString aEnabled = OStringToOUString(pEnabled, RTL_TEXTENCODING_UTF8);
         if (aEnabled != "true")
-            return;
+            return aLTLocales;
         OUString aBaseUrl = OStringToOUString(pBaseUrlString, 
RTL_TEXTENCODING_UTF8);
         try
         {
@@ -1071,6 +1073,11 @@ void setLanguageToolConfig()
             }
             batch->commit();
 
+            uno::Reference<linguistic2::XProofreader> xGC(
+                
xContext->getServiceManager()->createInstanceWithContext(u"org.openoffice.lingu.LanguageToolGrammarChecker"_ustr,
 xContext),
+                uno::UNO_QUERY_THROW);
+            uno::Reference<linguistic2::XSupportedLocales> xSuppLoc(xGC, 
uno::UNO_QUERY_THROW);
+
             css::uno::Reference<css::linguistic2::XLinguServiceManager2> 
xLangSrv =
                 css::linguistic2::LinguServiceManager::create(xContext);
             if (xLangSrv.is())
@@ -1081,11 +1088,6 @@ void setLanguageToolConfig()
                     Sequence<OUString> aEmpty;
                     Sequence<css::lang::Locale> aLocales = 
xSpell->getLocales();
 
-                    uno::Reference<linguistic2::XProofreader> xGC(
-                        
xContext->getServiceManager()->createInstanceWithContext(u"org.openoffice.lingu.LanguageToolGrammarChecker"_ustr,
 xContext),
-                        uno::UNO_QUERY_THROW);
-                    uno::Reference<linguistic2::XSupportedLocales> 
xSuppLoc(xGC, uno::UNO_QUERY_THROW);
-
                     for (int itLocale = 0; itLocale < aLocales.getLength(); 
itLocale++)
                     {
                         // turn off spell checker if LanguageTool supports the 
locale already
@@ -1095,12 +1097,16 @@ void setLanguageToolConfig()
                     }
                 }
             }
+
+            aLTLocales = xSuppLoc->getLocales();
         }
         catch(uno::Exception const& rException)
         {
             SAL_WARN("lok", "Failed to set LanguageTool API settings: " << 
rException.Message);
         }
     }
+
+    return aLTLocales;
 }
 
 }  // end anonymous namespace
@@ -7929,7 +7935,14 @@ static void preloadData()
     std::cerr << "
";
 
     // setup LanguageTool config before spell checking init
-    setLanguageToolConfig();
+    css::uno::Sequence<css::lang::Locale> aLTLocales = setLanguageToolConfig();
+    if (aLTLocales.getLength())
+    {
+        std::cerr << "Remote linguistic service languages: ";
+        for (auto &it : std::as_const(aLTLocales))
+            std::cerr << LanguageTag::convertToBcp47(it) << " ";
+        std::cerr << "
";
+    }
 
     // preload all available dictionaries
     
linguistic2::DictionaryList::create(comphelper::getProcessComponentContext());
@@ -7937,7 +7950,7 @@ static void preloadData()
         
css::linguistic2::LinguServiceManager::create(comphelper::getProcessComponentContext());
     css::uno::Reference<linguistic2::XSpellChecker> 
xSpellChecker(xLngSvcMgr->getSpellChecker());
 
-    std::cerr << "Preloading dictionaries: ";
+    std::cerr << "Preloading local dictionaries: ";
     css::uno::Reference<linguistic2::XSupportedLocales> 
xSpellLocales(xSpellChecker, css::uno::UNO_QUERY_THROW);
     uno::Sequence< css::lang::Locale > aLocales = xSpellLocales->getLocales();
     for (auto &it : std::as_const(aLocales))
@@ -7960,7 +7973,7 @@ static void preloadData()
     css::uno::Reference<linguistic2::XThesaurus> 
xThesaurus(xLngSvcMgr->getThesaurus());
     css::uno::Reference<linguistic2::XSupportedLocales> 
xThesLocales(xSpellChecker, css::uno::UNO_QUERY_THROW);
     aLocales = xThesLocales->getLocales();
-    std::cerr << "Preloading thesauri: ";
+    std::cerr << "Preloading local thesauri: ";
     for (auto &it : std::as_const(aLocales))
     {
         std::cerr << LanguageTag::convertToBcp47(it) << " ";
commit 26e433e0e3c6dfbf2569c3b6f0a14249dc4d0c1f
Author:     Caolán McNamara <[email protected]>
AuthorDate: Mon Sep 16 13:20:28 2024 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Tue Sep 17 08:38:18 2024 +0200

    move setLanguageToolConfig out of extern "C" zone
    
    no logic change here
    
    Change-Id: I29153a11e1b841fa078d29a6431cd5af1179672e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173450
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 0b1a56723eee..463ea4537987 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -811,6 +811,11 @@ static int lcl_getViewId(std::string_view payload)
     return 0;
 }
 
+// Wonder global state ...
+static uno::Reference<css::uno::XComponentContext> xContext;
+static uno::Reference<css::lang::XMultiServiceFactory> xSFactory;
+static uno::Reference<css::lang::XMultiComponentFactory> xFactory;
+
 namespace {
 
 std::string extractCertificate(const std::string & certificate)
@@ -1024,6 +1029,80 @@ void hideSidebar()
         SetLastExceptionMsg(u"No view shell or sidebar"_ustr);
 }
 
+void setLanguageToolConfig()
+{
+    const char* pEnabled = ::getenv("LANGUAGETOOL_ENABLED");
+    const char* pBaseUrlString = ::getenv("LANGUAGETOOL_BASEURL");
+
+    if (pEnabled && pBaseUrlString)
+    {
+        const char* pUsername = ::getenv("LANGUAGETOOL_USERNAME");
+        const char* pApikey = ::getenv("LANGUAGETOOL_APIKEY");
+        const char* pSSLVerification = 
::getenv("LANGUAGETOOL_SSL_VERIFICATION");
+        const char* pRestProtocol = ::getenv("LANGUAGETOOL_RESTPROTOCOL");
+
+        OUString aEnabled = OStringToOUString(pEnabled, RTL_TEXTENCODING_UTF8);
+        if (aEnabled != "true")
+            return;
+        OUString aBaseUrl = OStringToOUString(pBaseUrlString, 
RTL_TEXTENCODING_UTF8);
+        try
+        {
+            using LanguageToolCfg = 
officecfg::Office::Linguistic::GrammarChecking::LanguageTool;
+            auto batch(comphelper::ConfigurationChanges::create());
+
+            LanguageToolCfg::BaseURL::set(aBaseUrl, batch);
+            LanguageToolCfg::IsEnabled::set(true, batch);
+            if (pSSLVerification)
+            {
+                OUString aSSLVerification = 
OStringToOUString(pSSLVerification, RTL_TEXTENCODING_UTF8);
+                LanguageToolCfg::SSLCertVerify::set(aSSLVerification == 
"true", batch);
+            }
+            if (pRestProtocol)
+            {
+                OUString aRestProtocol = OStringToOUString(pRestProtocol, 
RTL_TEXTENCODING_UTF8);
+                LanguageToolCfg::RestProtocol::set(aRestProtocol, batch);
+            }
+            if (pUsername && pApikey)
+            {
+                OUString aUsername = OStringToOUString(pUsername, 
RTL_TEXTENCODING_UTF8);
+                OUString aApiKey = OStringToOUString(pApikey, 
RTL_TEXTENCODING_UTF8);
+                LanguageToolCfg::Username::set(aUsername, batch);
+                LanguageToolCfg::ApiKey::set(aApiKey, batch);
+            }
+            batch->commit();
+
+            css::uno::Reference<css::linguistic2::XLinguServiceManager2> 
xLangSrv =
+                css::linguistic2::LinguServiceManager::create(xContext);
+            if (xLangSrv.is())
+            {
+                css::uno::Reference<css::linguistic2::XSpellChecker> xSpell = 
xLangSrv->getSpellChecker();
+                if (xSpell.is())
+                {
+                    Sequence<OUString> aEmpty;
+                    Sequence<css::lang::Locale> aLocales = 
xSpell->getLocales();
+
+                    uno::Reference<linguistic2::XProofreader> xGC(
+                        
xContext->getServiceManager()->createInstanceWithContext(u"org.openoffice.lingu.LanguageToolGrammarChecker"_ustr,
 xContext),
+                        uno::UNO_QUERY_THROW);
+                    uno::Reference<linguistic2::XSupportedLocales> 
xSuppLoc(xGC, uno::UNO_QUERY_THROW);
+
+                    for (int itLocale = 0; itLocale < aLocales.getLength(); 
itLocale++)
+                    {
+                        // turn off spell checker if LanguageTool supports the 
locale already
+                        if (xSuppLoc->hasLocale(aLocales[itLocale]))
+                            xLangSrv->setConfiguredServices(
+                                SN_SPELLCHECKER, aLocales[itLocale], aEmpty);
+                    }
+                }
+            }
+        }
+        catch(uno::Exception const& rException)
+        {
+            SAL_WARN("lok", "Failed to set LanguageTool API settings: " << 
rException.Message);
+        }
+    }
+}
+
 }  // end anonymous namespace
 
 // Could be anonymous in principle, but for the unit testing purposes, we
@@ -2714,11 +2793,6 @@ void setFormatSpecificFilterData(std::u16string_view 
sFormat, comphelper::Sequen
 
 } // anonymous namespace
 
-// Wonder global state ...
-static uno::Reference<css::uno::XComponentContext> xContext;
-static uno::Reference<css::lang::XMultiServiceFactory> xSFactory;
-static uno::Reference<css::lang::XMultiComponentFactory> xFactory;
-
 static LibreOfficeKitDocument* lo_documentLoad(LibreOfficeKit* pThis, const 
char* pURL)
 {
     return lo_documentLoadWithOptions(pThis, pURL, nullptr);
@@ -7827,8 +7901,6 @@ static void preLoadShortCutAccelerators()
     batch->commit();
 }
 
-void setLanguageToolConfig();
-
 /// Used only by LibreOfficeKit when used by Online to pre-initialize
 static void preloadData()
 {
@@ -8090,80 +8162,6 @@ void setDeeplConfig()
     }
 }
 
-void setLanguageToolConfig()
-{
-    const char* pEnabled = ::getenv("LANGUAGETOOL_ENABLED");
-    const char* pBaseUrlString = ::getenv("LANGUAGETOOL_BASEURL");
-
-    if (pEnabled && pBaseUrlString)
-    {
-        const char* pUsername = ::getenv("LANGUAGETOOL_USERNAME");
-        const char* pApikey = ::getenv("LANGUAGETOOL_APIKEY");
-        const char* pSSLVerification = 
::getenv("LANGUAGETOOL_SSL_VERIFICATION");
-        const char* pRestProtocol = ::getenv("LANGUAGETOOL_RESTPROTOCOL");
-
-        OUString aEnabled = OStringToOUString(pEnabled, RTL_TEXTENCODING_UTF8);
-        if (aEnabled != "true")
-            return;
-        OUString aBaseUrl = OStringToOUString(pBaseUrlString, 
RTL_TEXTENCODING_UTF8);
-        try
-        {
-            using LanguageToolCfg = 
officecfg::Office::Linguistic::GrammarChecking::LanguageTool;
-            auto batch(comphelper::ConfigurationChanges::create());
-
-            LanguageToolCfg::BaseURL::set(aBaseUrl, batch);
-            LanguageToolCfg::IsEnabled::set(true, batch);
-            if (pSSLVerification)
-            {
-                OUString aSSLVerification = 
OStringToOUString(pSSLVerification, RTL_TEXTENCODING_UTF8);
-                LanguageToolCfg::SSLCertVerify::set(aSSLVerification == 
"true", batch);
-            }
-            if (pRestProtocol)
-            {
-                OUString aRestProtocol = OStringToOUString(pRestProtocol, 
RTL_TEXTENCODING_UTF8);
-                LanguageToolCfg::RestProtocol::set(aRestProtocol, batch);
-            }
-            if (pUsername && pApikey)
-            {
-                OUString aUsername = OStringToOUString(pUsername, 
RTL_TEXTENCODING_UTF8);
-                OUString aApiKey = OStringToOUString(pApikey, 
RTL_TEXTENCODING_UTF8);
-                LanguageToolCfg::Username::set(aUsername, batch);
-                LanguageToolCfg::ApiKey::set(aApiKey, batch);
-            }
-            batch->commit();
-
-            css::uno::Reference<css::linguistic2::XLinguServiceManager2> 
xLangSrv =
-                css::linguistic2::LinguServiceManager::create(xContext);
-            if (xLangSrv.is())
-            {
-                css::uno::Reference<css::linguistic2::XSpellChecker> xSpell = 
xLangSrv->getSpellChecker();
-                if (xSpell.is())
-                {
-                    Sequence<OUString> aEmpty;
-                    Sequence<css::lang::Locale> aLocales = 
xSpell->getLocales();
-
-                    uno::Reference<linguistic2::XProofreader> xGC(
-                        
xContext->getServiceManager()->createInstanceWithContext(u"org.openoffice.lingu.LanguageToolGrammarChecker"_ustr,
 xContext),
-                        uno::UNO_QUERY_THROW);
-                    uno::Reference<linguistic2::XSupportedLocales> 
xSuppLoc(xGC, uno::UNO_QUERY_THROW);
-
-                    for (int itLocale = 0; itLocale < aLocales.getLength(); 
itLocale++)
-                    {
-                        // turn off spell checker if LanguageTool supports the 
locale already
-                        if (xSuppLoc->hasLocale(aLocales[itLocale]))
-                            xLangSrv->setConfiguredServices(
-                                SN_SPELLCHECKER, aLocales[itLocale], aEmpty);
-                    }
-                }
-            }
-        }
-        catch(uno::Exception const& rException)
-        {
-            SAL_WARN("lok", "Failed to set LanguageTool API settings: " << 
rException.Message);
-        }
-    }
-}
-
 }
 
 static int lo_initialize(LibreOfficeKit* pThis, const char* pAppPath, const 
char* pUserProfileUrl)
commit 9031c056715fe43525d44704c05a1380b68eb278
Author:     Marco Cecchetti <[email protected]>
AuthorDate: Sun Sep 8 12:19:46 2024 +0200
Commit:     Szymon Kłos <[email protected]>
CommitDate: Mon Sep 16 20:26:57 2024 +0200

    lok: slideshow rework: check that requested slide is the expected one
    
    Change-Id: I225dfea9981d43fb90888f5025792e9d24d9a789
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173061
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Szymon Kłos <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 9ae5d7a93035..0b1a56723eee 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -1290,6 +1290,7 @@ static char* 
doc_getPresentationInfo(LibreOfficeKitDocument* pThis);
 
 static bool doc_createSlideRenderer(
     LibreOfficeKitDocument* pThis,
+    const char* pSlideHash,
     int nSlideNumber, unsigned* nViewWidth, unsigned* nViewHeight,
     bool bRenderBackground, bool bRenderMasterPage);
 
@@ -5703,6 +5704,7 @@ static char* 
doc_getPresentationInfo(LibreOfficeKitDocument* pThis)
 
 static bool doc_createSlideRenderer(
     LibreOfficeKitDocument* pThis,
+    const char* pSlideHash,
     int nSlideNumber, unsigned* pViewWidth, unsigned* pViewHeight,
     bool bRenderBackground, bool bRenderMasterPage)
 {
@@ -5716,9 +5718,11 @@ static bool doc_createSlideRenderer(
         return false;
     }
 
+    OString sSlideHash(pSlideHash);
     sal_Int32 nViewWidth = *pViewWidth;
     sal_Int32 nViewHeight = *pViewHeight;
     bool bReturn = pDoc->createSlideRenderer(
+                    sSlideHash,
                     nSlideNumber, nViewWidth, nViewHeight,
                     bRenderBackground, bRenderMasterPage);
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.h 
b/include/LibreOfficeKit/LibreOfficeKit.h
index 017351b5eb07..bf7f0fd8c1b3 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.h
+++ b/include/LibreOfficeKit/LibreOfficeKit.h
@@ -541,6 +541,7 @@ struct _LibreOfficeKitDocumentClass
     /// @see lok::Document::createSlideRenderer
     bool (*createSlideRenderer) (
         LibreOfficeKitDocument* pThis,
+        const char* pSlideHash,
         int nSlideNumber, unsigned* nViewWidth, unsigned* nViewHeight,
         bool bRenderBackground, bool bRenderMasterPage);
 
diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx 
b/include/LibreOfficeKit/LibreOfficeKit.hxx
index 6878c34b546b..ece999cbd6d7 100644
--- a/include/LibreOfficeKit/LibreOfficeKit.hxx
+++ b/include/LibreOfficeKit/LibreOfficeKit.hxx
@@ -917,11 +917,12 @@ public:
 
     /// Create a slide renderer in core for the input slide.
     bool createSlideRenderer(
+        const char* pSlideHash,
         int nSlideNumber, unsigned* nViewWidth, unsigned* nViewHeight,
         bool bRenderBackground, bool bRenderMasterPage)
     {
         return mpDoc->pClass->createSlideRenderer(
-            mpDoc, nSlideNumber, nViewWidth, nViewHeight, bRenderBackground, 
bRenderMasterPage);
+            mpDoc, pSlideHash, nSlideNumber, nViewWidth, nViewHeight, 
bRenderBackground, bRenderMasterPage);
     }
 
     /// Clean-up the slideshow (slide renderer)
diff --git a/include/vcl/ITiledRenderable.hxx b/include/vcl/ITiledRenderable.hxx
index 05db0bad6db0..9e57fc53b0a0 100644
--- a/include/vcl/ITiledRenderable.hxx
+++ b/include/vcl/ITiledRenderable.hxx
@@ -392,6 +392,7 @@ public:
     }
     /** Creates a slide show renderer (Impress only function) */
     virtual bool createSlideRenderer(
+        const OString& /*rSlideHash*/,
         sal_Int32 /*nSlideNumber*/, sal_Int32& /*nViewWidth*/, sal_Int32& 
/*nViewHeight*/,
         bool /*bRenderBackground*/, bool /*bRenderMasterPage*/)
    {
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 42a7a2fa2aad..72a71bc23fb9 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -32,6 +32,7 @@
 #include <svl/stritem.hxx>
 #include <svl/intitem.hxx>
 #include <comphelper/lok.hxx>
+#include <svx/unoapi.hxx>
 #include <svx/svdotable.hxx>
 #include <svx/svdoutl.hxx>
 #include <unotools/datetime.hxx>
@@ -46,6 +47,7 @@
 #include <drawdoc.hxx>
 #include <undo/undomanager.hxx>
 #include <sfx2/request.hxx>
+
 #include <svx/svxids.hrc>
 #include <pres.hxx>
 #include <navigatr.hxx>
@@ -3211,9 +3213,10 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering)
     CPPUNIT_ASSERT(pViewShell);
     SdPage* pPage = pViewShell->GetActualPage();
     CPPUNIT_ASSERT(pPage);
+    std::string sHash = GetInterfaceHash(GetXDrawPageForSdrPage(pPage));
     sal_Int32 nViewWidth = 2000;
     sal_Int32 nViewHeight = 2000;
-    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(0, nViewWidth, 
nViewHeight, true, true));
+    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(sHash.c_str(), 0, 
nViewWidth, nViewHeight, true, true));
     CPPUNIT_ASSERT_EQUAL(2000, nViewWidth);
     CPPUNIT_ASSERT_EQUAL(1125, nViewHeight);
 
@@ -3289,10 +3292,12 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_WithFie
     sd::ViewShell* pViewShell = 
pXImpressDocument->GetDocShell()->GetViewShell();
     CPPUNIT_ASSERT(pViewShell);
     SdPage* pPage = pViewShell->GetActualPage();
+
     CPPUNIT_ASSERT(pPage);
+    std::string sHash = GetInterfaceHash(GetXDrawPageForSdrPage(pPage));
     sal_Int32 nViewWidth = 2000;
     sal_Int32 nViewHeight = 2000;
-    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(0, nViewWidth, 
nViewHeight, true, true));
+    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(sHash.c_str(), 0, 
nViewWidth, nViewHeight, true, true));
     CPPUNIT_ASSERT_EQUAL(2000, nViewWidth);
     CPPUNIT_ASSERT_EQUAL(1125, nViewHeight);
 
@@ -3387,9 +3392,10 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
     CPPUNIT_ASSERT(pViewShell);
     SdPage* pPage = pViewShell->GetActualPage();
     CPPUNIT_ASSERT(pPage);
+    std::string sHash = GetInterfaceHash(GetXDrawPageForSdrPage(pPage));
     sal_Int32 nViewWidth = 2000;
     sal_Int32 nViewHeight = 2000;
-    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(0, nViewWidth, 
nViewHeight, true, true));
+    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(sHash.c_str(), 0, 
nViewWidth, nViewHeight, true, true));
     CPPUNIT_ASSERT_EQUAL(2000, nViewWidth);
     CPPUNIT_ASSERT_EQUAL(1125, nViewHeight);
 
@@ -3498,7 +3504,8 @@ CPPUNIT_TEST_FIXTURE(SdTiledRenderingTest, 
testSlideshowLayeredRendering_Animati
     CPPUNIT_ASSERT(pPage);
     sal_Int32 nViewWidth = 2000;
     sal_Int32 nViewHeight = 2000;
-    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(0, nViewWidth, 
nViewHeight, true, true));
+    std::string sHash = GetInterfaceHash(GetXDrawPageForSdrPage(pPage));
+    CPPUNIT_ASSERT(pXImpressDocument->createSlideRenderer(sHash.c_str(), 0, 
nViewWidth, nViewHeight, true, true));
     CPPUNIT_ASSERT_EQUAL(2000, nViewWidth);
     CPPUNIT_ASSERT_EQUAL(1125, nViewHeight);
 
diff --git a/sd/source/ui/inc/unomodel.hxx b/sd/source/ui/inc/unomodel.hxx
index f65eb0865a76..90134c120681 100644
--- a/sd/source/ui/inc/unomodel.hxx
+++ b/sd/source/ui/inc/unomodel.hxx
@@ -293,6 +293,7 @@ public:
     OString getPresentationInfo() const override;
     /// @see vcl::ITiledRenderable::createSlideRenderer().
     bool createSlideRenderer(
+        const OString& rSlideHash,
         sal_Int32 nSlideNumber, sal_Int32& nViewWidth, sal_Int32& nViewHeight,
         bool bRenderBackground, bool bRenderMasterPage) override;
     /// @see vcl::ITiledRenderable::postSlideshowCleanup().
diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx
index ff70d9074f7c..1b504fb8ebf9 100644
--- a/sd/source/ui/unoidl/unomodel.cxx
+++ b/sd/source/ui/unoidl/unomodel.cxx
@@ -4485,12 +4485,38 @@ namespace
 {
 // use VCL slideshow renderer or not - leave the old one in for now, so it is 
possible to compare output
 constexpr const bool bVCLSlideShowRenderer = true;
+
+bool isRequestedSlideValid(SdDrawDocument* mpDoc, sal_Int32 nSlideNumber, 
const std::string& slideHash)
+{
+    try
+    {
+        uno::Reference<drawing::XDrawPagesSupplier> 
xDrawPages(mpDoc->getUnoModel(),
+                                                               
uno::UNO_QUERY_THROW);
+        uno::Reference<container::XIndexAccess> 
xSlides(xDrawPages->getDrawPages(),
+                                                        uno::UNO_QUERY_THROW);
+        uno::Reference<drawing::XDrawPage> 
xSlide(xSlides->getByIndex(nSlideNumber),
+                                                  uno::UNO_QUERY_THROW);
+        if (xSlide.is()) {
+            return slideHash == GetInterfaceHash(xSlide);
+        }
+    }
+    catch (uno::Exception&)
+    {
+        TOOLS_WARN_EXCEPTION( "sd", 
"SdXImpressDocument::createLOKSlideRenderer: failed" );
+    }
+    return false;
+}
 }
 
 bool SdXImpressDocument::createSlideRenderer(
+    const OString& rSlideHash,
     sal_Int32 nSlideNumber, sal_Int32& nViewWidth, sal_Int32& nViewHeight,
     bool bRenderBackground, bool bRenderMasterPage)
 {
+    std::string sSlideHash(rSlideHash);
+    if (!isRequestedSlideValid(mpDoc, nSlideNumber, sSlideHash))
+        return false;
+
     if (bVCLSlideShowRenderer)
     {
         SdPage* pPage = mpDoc->GetSdPage(sal_uInt16(nSlideNumber), 
PageKind::Standard);
commit 9e30eb5b0679d1116b15d1979938dc94c261a98a
Author:     Caolán McNamara <[email protected]>
AuthorDate: Sat Sep 14 13:44:24 2024 +0100
Commit:     Andras Timar <[email protected]>
CommitDate: Mon Sep 16 11:20:25 2024 +0200

    null deref in SwXTextDocument::initializeForTiledRendering
    
     #0  SwDocShell::GetWrtShell (this=0x0) at sw/inc/docsh.hxx:226
     #1  
SwXTextDocument::initializeForTiledRendering(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>
 const&) ()
         at sw/source/uibase/uno/unotxdoc.cxx:3634
     #2  0x00007f6bb1d40734 in doc_initializeForRendering () at 
include/com/sun/star/uno/Type.h:163
     #3  0x00000000005d7988 in lok::Document::initializeForRendering (
         pArguments=0x342d0e48 
"{\".uno:Author\":{\"type\":\"string\",\"value\":\"1(访客)\"},\".uno:ChangeTheme\":{\"type\":\"string\",\"value\":\"Light\"},\".uno:InvertBackground\":{\"type\":\"string\",\"value\":\"Light\"}}",
 this=<optimized out>) at 
/home/collabora/jenkins/workspace/package_cool_24.04_rpm/rpmbuild/BUILD/coolwsd-24.04.7.2snapshot/bundled/include/LibreOfficeKit/LibreOfficeKit.hxx:245
     #4  Document::load(std::shared_ptr<ChildSession> const&, std::string 
const&) () at kit/Kit.cpp:1949
     #5  0x00000000005da3b2 in Document::onLoad(std::string const&, std::string 
const&, std::string const&) () at kit/Kit.cpp:1226
     #6  0x000000000057f7c1 in ChildSession::loadDocument(StringVector const&) 
() at kit/ChildSession.cpp:906
     #7  0x0000000000586464 in ChildSession::_handleInput(char const*, int) () 
at kit/ChildSession.cpp:298
     #8  0x0000000000613e48 in Session::handleMessage(std::vector<char, 
std::allocator<char> > const&) () at 
/opt/rh/devtoolset-12/root/usr/include/c++/12/bits/stl_vector.h:987
     #9  0x00000000005c67ac in Document::forwardToChild(std::string const&, 
std::vector<char, std::allocator<char> > const&) () at kit/Kit.cpp:2052
     #10 0x00000000005c7b29 in Document::drainQueue() () at kit/Kit.cpp:2279
     #11 0x00000000005c80d8 in KitSocketPoll::drainQueue (this=0x34316d30) at 
kit/Kit.cpp:2676
    
    Change-Id: I6f18f1a542ca96fe3fda0248e15ee1254eb9ca95
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173364
    Tested-by: Andras Timar <[email protected]>
    Reviewed-by: Andras Timar <[email protected]>

diff --git a/sw/source/uibase/uno/unotxdoc.cxx 
b/sw/source/uibase/uno/unotxdoc.cxx
index 2cffa5af217f..4125910105a2 100644
--- a/sw/source/uibase/uno/unotxdoc.cxx
+++ b/sw/source/uibase/uno/unotxdoc.cxx
@@ -3631,12 +3631,18 @@ void SwXTextDocument::initializeForTiledRendering(const 
css::uno::Sequence<css::
 {
     SolarMutexGuard aGuard;
 
-    SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
+    if (!IsValid())
+    {
+        SAL_WARN("sw.uno", "no DocShell when attempting to initialize for 
tiled rendering");
+        return;
+    }
 
     SwView* pView = m_pDocShell->GetView();
     if (!pView)
         return;
 
+    SwViewShell* pViewShell = m_pDocShell->GetWrtShell();
+
     pView->SetViewLayout(1/*nColumns*/, false/*bBookMode*/, true);
 
     // Tiled rendering defaults.
commit 3bb2668f5e753e9fa6aa7eea74454bf11cdfc853
Author:     Jaume Pujantell <[email protected]>
AuthorDate: Sun Sep 8 20:52:28 2024 +0200
Commit:     Mike Kaganski <[email protected]>
CommitDate: Mon Sep 16 09:46:24 2024 +0200

    sw: add new command to make a response comment root
    
    Adds the option to convert a reply comment into a new top comment
    while preserving the parent-child realtions of the other comments
    in the thread.
    
    Change-Id: I3cd5e5466fadc2226651d7c244b5139ec2d1f949
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/173051
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Mike Kaganski <[email protected]>

diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 37d9596839fe..9ae5d7a93035 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -3860,6 +3860,7 @@ static void doc_iniUnoCommands ()
         u".uno:ReplyComment"_ustr,
         u".uno:ResolveComment"_ustr,
         u".uno:ResolveCommentThread"_ustr,
+        u".uno:PromoteComment"_ustr,
         u".uno:InsertRowsBefore"_ustr,
         u".uno:InsertRowsAfter"_ustr,
         u".uno:InsertColumnsBefore"_ustr,
diff --git 
a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu 
b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
index 6567f42c538e..30896cc0cdbc 100644
--- a/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
+++ b/officecfg/registry/data/org/openoffice/Office/UI/GenericCommands.xcu
@@ -6541,6 +6541,14 @@ bit 3 (0x8): #define 
UICOMMANDDESCRIPTION_PROPERTIES_TOGGLEBUTTON 8
           <value>1</value>
         </prop>
       </node>
+      <node oor:name=".uno:PromoteComment" oor:op="replace">
+        <prop oor:name="Label" oor:type="xs:string">
+          <value xml:lang="en-US">Promote Comment To Root</value>
+        </prop>
+        <prop oor:name="Properties" oor:type="xs:int">
+          <value>1</value>
+        </prop>
+      </node>
       <node oor:name=".uno:CellVertTop" oor:op="replace">
         <prop oor:name="Label" oor:type="xs:string">
           <value xml:lang="en-US">Top</value>
diff --git a/sfx2/source/control/dispatch.cxx b/sfx2/source/control/dispatch.cxx
index 958f493f01a3..d08e02e2f452 100644
--- a/sfx2/source/control/dispatch.cxx
+++ b/sfx2/source/control/dispatch.cxx
@@ -1532,6 +1532,7 @@ bool SfxDispatcher::IsCommandAllowedInLokReadOnlyViewMode 
(OUString commandName)
         u".uno:DeleteComment"_ustr,
         u".uno:DeleteAnnotation"_ustr,
         u".uno:EditAnnotation"_ustr,
+        u".uno:PromoteComment"_ustr,
     };
 
     if (std::find(std::begin(allowedList), std::end(allowedList), commandName) 
!= std::end(allowedList))
diff --git a/sfx2/source/control/unoctitm.cxx b/sfx2/source/control/unoctitm.cxx
index 5e48967fc6b8..720062c8b3cb 100644
--- a/sfx2/source/control/unoctitm.cxx
+++ b/sfx2/source/control/unoctitm.cxx
@@ -1179,6 +1179,7 @@ constexpr auto handlers = 
frozen::make_unordered_map<std::u16string_view, Payloa
     { u"DeleteAnnotation", EnabledPayload },
     { u"ResolveAnnotation", EnabledPayload },
     { u"ResolveAnnotationThread", EnabledPayload },
+    { u"PromoteComment", EnabledPayload },
     { u"InsertRowsBefore", EnabledPayload },
     { u"InsertRowsAfter", EnabledPayload },
     { u"InsertColumnsBefore", EnabledPayload },
diff --git a/sw/inc/AnnotationWin.hxx b/sw/inc/AnnotationWin.hxx
index cbeaf7ceca44..aee382e51a82 100644
--- a/sw/inc/AnnotationWin.hxx
+++ b/sw/inc/AnnotationWin.hxx
@@ -206,6 +206,9 @@ class SAL_DLLPUBLIC_RTTI SwAnnotationWin final : public 
InterimItemWindow
 
         virtual FactoryFunction GetUITestFactory() const override;
 
+        bool IsRootNote() const;
+        void SetAsRoot();
+
     private:
 
         virtual void    LoseFocus() override;
diff --git a/sw/inc/PostItMgr.hxx b/sw/inc/PostItMgr.hxx
index 5a877a6c8afe..535ae5f05165 100644
--- a/sw/inc/PostItMgr.hxx
+++ b/sw/inc/PostItMgr.hxx
@@ -207,6 +207,8 @@ class SAL_DLLPUBLIC_RTTI SwPostItMgr final : public 
SfxListener
         void DeleteCommentThread(sal_uInt32 nPostItId);
         void ToggleResolved(sal_uInt32 nPostItId);
         void ToggleResolvedForThread(sal_uInt32 nPostItId);
+        void PromoteToRoot(sal_uInt32 nPostItId);
+        void MoveSubthreadToRoot(const sw::annotation::SwAnnotationWin* 
pNewRoot);
 
         void ExecuteFormatAllDialog(SwView& rView);
         void FormatAll(const SfxItemSet &rNewAttr);
diff --git a/sw/inc/cmdid.h b/sw/inc/cmdid.h
index acc812fb4dd3..e9796f028f6f 100644
--- a/sw/inc/cmdid.h
+++ b/sw/inc/cmdid.h
@@ -804,6 +804,7 @@ class SwUINumRuleItem;
 #define FN_RESOLVE_NOTE             (FN_NOTES+9)
 #define FN_RESOLVE_NOTE_THREAD      (FN_NOTES+10)
 #define FN_DELETE_COMMENT_THREAD    (FN_NOTES+11)
+#define FN_PROMOTE_COMMENT          (FN_NOTES+12)
 
 // Region: Parameter
 #define FN_PARAM_MOVE_COUNT         TypedWhichId<SfxInt32Item>(FN_PARAM+2)
diff --git a/sw/sdi/_annotsh.sdi b/sw/sdi/_annotsh.sdi
index 919dd0513aa5..0c26a55dd6d0 100644
--- a/sw/sdi/_annotsh.sdi
+++ b/sw/sdi/_annotsh.sdi
@@ -78,6 +78,12 @@ interface _Annotation
         StateMethod = GetNoteState ;
     ]
 
+    FN_PROMOTE_COMMENT
+    [
+        ExecMethod = NoteExec ;
+        StateMethod = GetNoteState ;
+    ]
+
     FN_POSTIT
         [
                 ExecMethod = NoteExec ;
diff --git a/sw/sdi/_textsh.sdi b/sw/sdi/_textsh.sdi
index a562847648d2..8c9aef9be2a1 100644
--- a/sw/sdi/_textsh.sdi
+++ b/sw/sdi/_textsh.sdi
@@ -1110,6 +1110,11 @@ interface BaseText
         ExecMethod = ExecField ;
         StateMethod = StateField;
     ]
+    FN_PROMOTE_COMMENT
+    [
+        ExecMethod = ExecField ;
+        StateMethod = StateField;
+    ]
     FN_REDLINE_COMMENT // status(play)
     [
         ExecMethod = ExecField ;
diff --git a/sw/sdi/swriter.sdi b/sw/sdi/swriter.sdi
index 8679f7cb129d..77ef4f2e3332 100644
--- a/sw/sdi/swriter.sdi
+++ b/sw/sdi/swriter.sdi
@@ -7869,6 +7869,23 @@ SfxStringItem HideAuthor FN_HIDE_NOTE_AUTHOR ( 
SfxStringItem Author FN_HIDE_NOTE
     GroupId = SfxGroupId::Edit;
 ]
 
+SfxVoidItem PromoteComment FN_PROMOTE_COMMENT
+(SvxPostItIdItem Id SID_ATTR_POSTIT_ID)
+[
+    AutoUpdate = FALSE,
+    FastCall = FALSE,
+    ReadOnlyDoc = FALSE,
+    Toggle = FALSE,
+    Container = FALSE,
+    RecordAbsolute = FALSE,
+    RecordPerSet;
+
+    AccelConfig = TRUE,
+    MenuConfig = TRUE,
+    ToolBoxConfig = TRUE,
+    GroupId = SfxGroupId::Edit;
+]
+
 SvxViewLayoutItem ViewLayout SID_ATTR_VIEWLAYOUT
 [
         AutoUpdate = FALSE,
diff --git a/sw/source/uibase/docvw/AnnotationMenuButton.cxx 
b/sw/source/uibase/docvw/AnnotationMenuButton.cxx
index 5e42d15c879e..ac8dd0c8e031 100644
--- a/sw/source/uibase/docvw/AnnotationMenuButton.cxx
+++ b/sw/source/uibase/docvw/AnnotationMenuButton.cxx
@@ -55,6 +55,8 @@ IMPL_LINK(SwAnnotationWin, SelectHdl, const OUString&, 
rIdent, void)
         ExecuteCommand(FN_DELETE_ALL_NOTES);
     else if (rIdent == "formatall")
         ExecuteCommand(FN_FORMAT_ALL_NOTES);
+    else if (rIdent == "promote")
+        ExecuteCommand(FN_PROMOTE_COMMENT);
 
     if (bSwitchedFocus)
         UnsetActiveSidebarWin();
@@ -76,6 +78,7 @@ IMPL_LINK_NOARG(SwAnnotationWin, ToggleHdl, 
weld::Toggleable&, void)
         mxMenuButton->set_item_visible("resolvethread", false);
         mxMenuButton->set_item_visible("unresolvethread", false);
         mxMenuButton->set_item_visible("delete", false );
+        mxMenuButton->set_item_visible("promote", false);
     }
     else
     {
@@ -86,6 +89,7 @@ IMPL_LINK_NOARG(SwAnnotationWin, ToggleHdl, 
weld::Toggleable&, void)
         mxMenuButton->set_item_visible("resolvethread", !IsThreadResolved());
         mxMenuButton->set_item_visible("unresolvethread", IsThreadResolved());
         mxMenuButton->set_item_visible("delete", !IsReadOnlyOrProtected());
+        mxMenuButton->set_item_visible("promote", !IsReadOnlyOrProtected() && 
!IsRootNote());
     }
 
     mxMenuButton->set_item_visible("deletethread", !bReadOnly);
diff --git a/sw/source/uibase/docvw/AnnotationWin.cxx 
b/sw/source/uibase/docvw/AnnotationWin.cxx
index 426c097e9e58..75569fcd5cf3 100644
--- a/sw/source/uibase/docvw/AnnotationWin.cxx
+++ b/sw/source/uibase/docvw/AnnotationWin.cxx
@@ -307,6 +307,24 @@ bool SwAnnotationWin::IsThreadResolved()
     }
 }
 
+bool SwAnnotationWin::IsRootNote() const
+{
+    return 
static_cast<SwPostItField*>(mpFormatField->GetField())->GetParentPostItId() == 
0;
+}
+
+void SwAnnotationWin::SetAsRoot()
+{
+    if (!IsRootNote())
+    {
+        SwPostItField* pPostIt = 
static_cast<SwPostItField*>(mpFormatField->GetField());
+        pPostIt->SetParentId(0);
+        pPostIt->SetParentPostItId(0);
+        pPostIt->SetParentName("");
+        mrMgr.MoveSubthreadToRoot(this);
+        mpFormatField->Broadcast(SwFormatFieldHint(nullptr, 
SwFormatFieldHintWhich::CHANGED));
+    }
+}
+
 void SwAnnotationWin::UpdateData()
 {
     if ( mpOutliner->IsModified() || mbResolvedStateUpdated )
diff --git a/sw/source/uibase/docvw/AnnotationWin2.cxx 
b/sw/source/uibase/docvw/AnnotationWin2.cxx
index 73c035abdaf7..e1feb6bda484 100644
--- a/sw/source/uibase/docvw/AnnotationWin2.cxx
+++ b/sw/source/uibase/docvw/AnnotationWin2.cxx
@@ -1072,10 +1072,10 @@ void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
             {
                 // Get newly created SwPostItField and set its paraIdParent
                 auto pPostItField = mrMgr.GetLatestPostItField();
-                pPostItField->SetParentId(GetTopReplyNote()->GetParaId());
-                
pPostItField->SetParentPostItId(GetTopReplyNote()->GetPostItField()->GetPostItId());
+                pPostItField->SetParentId(GetParaId());
+                
pPostItField->SetParentPostItId(GetPostItField()->GetPostItId());
                 this->GeneratePostItName();
-                
pPostItField->SetParentName(GetTopReplyNote()->GetPostItField()->GetName());
+                pPostItField->SetParentName(GetPostItField()->GetName());
 
                 // In this case, force generating the associated window
                 // synchronously so we can bundle its use of the registered
@@ -1126,6 +1126,12 @@ void SwAnnotationWin::ExecuteCommand(sal_uInt16 nSlot)
             mrView.GetViewFrame().GetBindings().Execute( nSlot, aItems, 
SfxCallMode::ASYNCHRON );
         }
             break;
+        case FN_PROMOTE_COMMENT:
+            SetAsRoot();
+            DoResize();
+            Invalidate();
+            mrMgr.LayoutPostIts();
+            break;
         default:
             mrView.GetViewFrame().GetBindings().Execute( nSlot );
             break;
diff --git a/sw/source/uibase/docvw/PostItMgr.cxx 
b/sw/source/uibase/docvw/PostItMgr.cxx
index f712188bcba2..bc4df5ecb409 100644
--- a/sw/source/uibase/docvw/PostItMgr.cxx
+++ b/sw/source/uibase/docvw/PostItMgr.cxx
@@ -1713,6 +1713,62 @@ void SwPostItMgr::Delete()
     LayoutPostIts();
 }
 
+void SwPostItMgr::PromoteToRoot(sal_uInt32 nPostItId)
+{
+    mpWrtShell->StartAllAction();
+
+    SwRewriter aRewriter;
+    aRewriter.AddRule(UndoArg1, SwResId(STR_CONTENT_TYPE_SINGLE_POSTIT));
+
+    // We have no undo ID at the moment.
+
+    IsPostitFieldWithPostitId aFilter(nPostItId);
+    FieldDocWatchingStack aStack(mvPostItFields, *mpView->GetDocShell(), 
aFilter);
+    const SwFormatField* pField = aStack.pop();
+    // pField now contains our AnnotationWin object
+    if (pField)
+    {
+        SwAnnotationWin* pWin = GetSidebarWin(pField);
+        pWin->SetAsRoot();
+    }
+    PrepareView();
+    mpWrtShell->EndAllAction();
+    mbLayout = true;
+    CalcRects();
+    LayoutPostIts();
+}
+
+void SwPostItMgr::MoveSubthreadToRoot(const sw::annotation::SwAnnotationWin* 
pNewRoot)
+{
+    std::vector<std::unique_ptr<SwSidebarItem>>::iterator first, middle, last;
+    first = std::find_if(mvPostItFields.begin(), mvPostItFields.end(),
+                         [&pNewRoot](const std::unique_ptr<SwSidebarItem>& 
pField) {
+                             return pField->mpPostIt == pNewRoot;
+                         });
+    if (first == mvPostItFields.end())
+        return;
+    std::set<int> aPostItIds;
+    aPostItIds.insert(pNewRoot->GetPostItField()->GetPostItId());
+    middle = first + 1;
+    while (middle != mvPostItFields.end()
+           && 
aPostItIds.contains((*middle)->mpPostIt->GetPostItField()->GetParentPostItId()))
+    {
+        
aPostItIds.insert((*middle)->mpPostIt->GetPostItField()->GetPostItId());
+        ++middle;
+    }
+    if (middle == mvPostItFields.end())
+        return;
+    last = middle;
+    while (last != mvPostItFields.end()
+           && (*last)->mpPostIt->GetPostItField()->GetParentPostItId() != 0)
+        ++last;
+    if (last == middle)
+        return;
+    std::rotate(first, middle, last);
+    CalcRects();
+    LayoutPostIts();
+}
+
 void SwPostItMgr::ExecuteFormatAllDialog(SwView& rView)
 {
     if (mvPostItFields.empty())
diff --git a/sw/source/uibase/shells/annotsh.cxx 
b/sw/source/uibase/shells/annotsh.cxx
index 5c9ed82b4114..4d87aacd451e 100644
--- a/sw/source/uibase/shells/annotsh.cxx
+++ b/sw/source/uibase/shells/annotsh.cxx
@@ -1114,6 +1114,7 @@ void SwAnnotationShell::NoteExec(SfxRequest const &rReq)
         case FN_DELETE_COMMENT_THREAD:
         case FN_RESOLVE_NOTE:
         case FN_RESOLVE_NOTE_THREAD:
+        case FN_PROMOTE_COMMENT:
             if ( pPostItMgr->HasActiveSidebarWin() )
                 pPostItMgr->GetActiveSidebarWin()->ExecuteCommand(nSlot);
             break;
@@ -1240,6 +1241,15 @@ void SwAnnotationShell::GetNoteState(SfxItemSet &rSet)
                 }
                 break;
             }
+        case FN_PROMOTE_COMMENT:
+            {
+                if (!pPostItMgr || !pPostItMgr->HasActiveAnnotationWin()
+                    || pPostItMgr->GetActiveSidebarWin()->IsRootNote())
+                {
+                    rSet.DisableItem(nWhich);
+                }
+                break;
+            }
             default:
                 rSet.InvalidateItem( nWhich );
                 break;
diff --git a/sw/source/uibase/shells/textfld.cxx 
b/sw/source/uibase/shells/textfld.cxx
index 87aa34ffd724..d20a37ffe1d3 100644
--- a/sw/source/uibase/shells/textfld.cxx
+++ b/sw/source/uibase/shells/textfld.cxx
@@ -506,18 +506,6 @@ void SwTextShell::ExecField(SfxRequest &rReq)
                             sText = pTextItem->GetValue();
                         pMgr->RegisterAnswerText(sText);
                         pWin->ExecuteCommand(nSlot);
-
-                        SwPostItField* pLatestPostItField = 
pMgr->GetLatestPostItField();
-                        if (pLatestPostItField)
-                        {
-                            // Set the parent postit id of the reply.
-                            
pLatestPostItField->SetParentPostItId(pIdItem->GetValue().toUInt32());
-
-                            // If name of the replied comment is empty, we 
need to set a name in order to connect them in the xml file.
-                            pWin->GeneratePostItName(); // Generates a name if 
the current name is empty.
-
-                            
pLatestPostItField->SetParentName(pWin->GetPostItField()->GetName());
-                        }
                     }
                 }
             }
@@ -549,6 +537,15 @@ void SwTextShell::ExecField(SfxRequest &rReq)
             }
         }
         break;
+        case FN_PROMOTE_COMMENT:
+        {
+            const SvxPostItIdItem* pIdItem = 
rReq.GetArg<SvxPostItIdItem>(SID_ATTR_POSTIT_ID);
+            if (pIdItem && !pIdItem->GetValue().isEmpty() && 
GetView().GetPostItMgr())
+            {
+                
GetView().GetPostItMgr()->PromoteToRoot(pIdItem->GetValue().toUInt32());
+            }
+            break;
+        }
         case FN_REDLINE_COMMENT:
         {
             /*  this code can be used once we want redline comments in the 
margin, all other stuff can
diff --git a/sw/uiconfig/sglobal/menubar/menubar.xml 
b/sw/uiconfig/sglobal/menubar/menubar.xml
index d0b9a1c4c1b0..b9968638edd1 100644
--- a/sw/uiconfig/sglobal/menubar/menubar.xml
+++ b/sw/uiconfig/sglobal/menubar/menubar.xml
@@ -146,6 +146,7 @@
           <menu:menuitem menu:id=".uno:ReplyComment" menu:style="text"/>
           <menu:menuitem menu:id=".uno:ResolveComment" menu:style="text"/>
           <menu:menuitem menu:id=".uno:ResolveCommentThread" 
menu:style="text"/>
+          <menu:menuitem menu:id=".uno:PromoteComment" menu:syle="text"/>
           <menu:menuitem menu:id=".uno:DeleteComment" menu:style="text"/>
           <menu:menuitem menu:id=".uno:DeleteCommentThread" menu:style="text"/>
           <menu:menuitem menu:id=".uno:DeleteAuthor" menu:style="text"/>
diff --git a/sw/uiconfig/sglobal/popupmenu/annotation.xml 
b/sw/uiconfig/sglobal/popupmenu/annotation.xml
index 42c89cd7c8bc..91da8b30cbfc 100644
--- a/sw/uiconfig/sglobal/popupmenu/annotation.xml
+++ b/sw/uiconfig/sglobal/popupmenu/annotation.xml
@@ -21,6 +21,7 @@
   <menu:menuitem menu:id=".uno:ReplyComment"/>
   <menu:menuitem menu:id=".uno:ResolveComment"/>
   <menu:menuitem menu:id=".uno:ResolveCommentThread"/>
+  <menu:menuitem menu:id=".uno:PromoteComment"/>
   <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:DeleteComment"/>
   <menu:menuitem menu:id=".uno:DeleteCommentThread"/>
diff --git a/sw/uiconfig/swriter/menubar/menubar.xml 
b/sw/uiconfig/swriter/menubar/menubar.xml
index 281b77afe16e..a61844f3699a 100644
--- a/sw/uiconfig/swriter/menubar/menubar.xml
+++ b/sw/uiconfig/swriter/menubar/menubar.xml
@@ -151,6 +151,7 @@
           <menu:menuitem menu:id=".uno:ReplyComment" menu:style="text"/>
           <menu:menuitem menu:id=".uno:ResolveComment" menu:style="text"/>
           <menu:menuitem menu:id=".uno:ResolveCommentThread" 
menu:style="text"/>
+          <menu:menuitem menu:id=".uno:PromoteComment" menu:style="text"/>
           <menu:menuitem menu:id=".uno:DeleteComment" menu:style="text"/>
           <menu:menuitem menu:id=".uno:DeleteCommentThread" menu:style="text"/>
           <menu:menuitem menu:id=".uno:DeleteAuthor" menu:style="text"/>
diff --git a/sw/uiconfig/swriter/popupmenu/annotation.xml 
b/sw/uiconfig/swriter/popupmenu/annotation.xml
index acdc6551ea97..bda8f346e374 100644
--- a/sw/uiconfig/swriter/popupmenu/annotation.xml
+++ b/sw/uiconfig/swriter/popupmenu/annotation.xml
@@ -22,6 +22,7 @@
   <menu:menuseparator/>
   <menu:menuitem menu:id=".uno:ResolveComment"/>
   <menu:menuitem menu:id=".uno:ResolveCommentThread"/>
+  <menu:menuitem menu:id=".uno:PromoteComment"/>
   <menu:menuitem menu:id=".uno:DeleteComment"/>
   <menu:menuitem menu:id=".uno:DeleteCommentThread"/>
   <menu:menuitem menu:id=".uno:DeleteAuthor"/>
diff --git a/sw/uiconfig/swriter/ui/annotation.ui 
b/sw/uiconfig/swriter/ui/annotation.ui
index fc0e4c39a1a2..31b3c90b8aed 100644
--- a/sw/uiconfig/swriter/ui/annotation.ui
+++ b/sw/uiconfig/swriter/ui/annotation.ui
@@ -57,6 +57,14 @@
         <property name="use-underline">True</property>
       </object>
     </child>
+    <child>
+      <object class="GtkMenuItem" id="promote">
+        <property name="visible">True</property>
+        <property name="can-focus">False</property>
+        <property name="label" translatable="yes" 
context="annotationmenu|promote">Promote Comment</property>
+        <property name="use-underline">True</property>
+      </object>
+    </child>
     <child>
       <object class="GtkMenuItem" id="delete">
         <property name="visible">True</property>
diff --git a/sw/uiconfig/swriter/ui/notebookbar_groupedbar_full.ui 
b/sw/uiconfig/swriter/ui/notebookbar_groupedbar_full.ui
index 430b016a4e5a..b642cccf6b71 100644
--- a/sw/uiconfig/swriter/ui/notebookbar_groupedbar_full.ui
+++ b/sw/uiconfig/swriter/ui/notebookbar_groupedbar_full.ui
@@ -343,6 +343,13 @@
         <property name="action_name">.uno:ResolveCommentThread</property>
       </object>
     </child>
+    <child>
+      <object class="GtkMenuItem" id="MenuComments-PromoteComment">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="action_name">.uno:PromoteComment</property>
+      </object>
+    </child>
     <child>
       <object class="GtkMenuItem" id="MenuComments-DeleteAuthor">
         <property name="visible">True</property>

Reply via email to