desktop/source/lib/init.cxx | 172 +++++++++ lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx | 69 +++ lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx | 2 linguistic/CppunitTest_linguistic_restprotocol.mk | 39 ++ linguistic/Module_linguistic.mk | 7 linguistic/qa/restprotocol.cxx | 181 ++++++++++ sc/source/ui/docshell/docsh.cxx | 3 sc/source/ui/view/gridwin.cxx | 13 8 files changed, 473 insertions(+), 13 deletions(-)
New commits: commit 6c5c4f42b52486e39b6ebff94d4f25371d8bccbd Author: Henry Castro <hcas...@collabora.com> AuthorDate: Wed Dec 14 11:40:16 2022 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:45 2023 -0400 lok:sc: do not generate extra mouseup events In tiled rendering case, the client side always will send the pair mousedown/mouseup events to server side, it is not necessary to generate extra mouseup events when the mouse tracking has ended, otherwise the selection engine will receive two mouseup events and wrong selection states. Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: I99983de9591e26f6e5327fff63c45e682cbf1999 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144168 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Michael Meeks <michael.me...@collabora.com> diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 547338589298..ca863a848a38 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -2879,11 +2879,14 @@ void ScGridWindow::Tracking( const TrackingEvent& rTEvt ) } else if ( rTEvt.IsTrackingEnded() ) { - // MouseButtonUp always with matching buttons (eg for test tool, # 63148 #) - // The tracking event will indicate if it was completed and not canceled. - MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(), - rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() ); - MouseButtonUp( aUpEvt ); + if (!comphelper::LibreOfficeKit::isActive()) + { + // MouseButtonUp always with matching buttons (eg for test tool, # 63148 #) + // The tracking event will indicate if it was completed and not canceled. + MouseEvent aUpEvt( rMEvt.GetPosPixel(), rMEvt.GetClicks(), + rMEvt.GetMode(), nButtonDown, rMEvt.GetModifier() ); + MouseButtonUp( aUpEvt ); + } } else MouseMove( rMEvt ); commit cfef44584f0ab1ef23d5d986b862e8097126a8ae Author: Henry Castro <hcas...@collabora.com> AuthorDate: Thu Jan 5 11:32:32 2023 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:45 2023 -0400 lok: sc: avoid the shared spreadsheet dialog It is not needed the LO core shared spreadsheet because the online has collaborative functionality turns on by default. Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: I57ab83eae2913522d55704ae5a115e30c9d10034 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145091 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Andras Timar <andras.ti...@collabora.com> diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 458feb6dea2a..9a5b5968d9ec 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -727,7 +727,8 @@ void ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) #endif #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT - if ( IsDocShared() && !SC_MOD()->IsInSharedDocLoading() ) + if ( IsDocShared() && !SC_MOD()->IsInSharedDocLoading() + && !comphelper::LibreOfficeKit::isActive() ) { ScAppOptions aAppOptions = SC_MOD()->GetAppOptions(); if ( aAppOptions.GetShowSharedDocumentWarning() ) commit e78c76a250a90e553978c68c402540869b53fa8c Author: Henry Castro <hcas...@collabora.com> AuthorDate: Tue Jan 17 11:02:13 2023 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:45 2023 -0400 lok: fix query language status The Calc and Impress return language status as a SfxStringItem, but Writer is a SfxListStringItem. Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: I88f77288e422a8f80473f0e33257078cfaa704b8 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145675 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Andras Timar <andras.ti...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146479 Tested-by: Jenkins diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 49a3a2f1a49e..9e36d464b75f 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -5393,22 +5393,34 @@ static void getDocLanguages(LibreOfficeKitDocument* pThis, uno::Sequence<lang::L css::uno::Any aLangStatus; pDispatcher->QueryState(SID_LANGUAGE_STATUS, aLangStatus); - Sequence<OUString> aSeqLang; - if (!(aLangStatus >>= aSeqLang)) - return; + OUString sCurrent; + OUString sKeyboard; + OUString sGuessText; + SvtScriptType eScriptType = SvtScriptType::LATIN | SvtScriptType::ASIAN + | SvtScriptType::COMPLEX; - // (aSeqLang[0] == "Current Language", aSeqLang[1] == "Script Type", - // aSeqLang[2] == "Keyboard Language", aSeqLang[3] == "Guess Text Lang") - if (aSeqLang.getLength() != 4) - return; + Sequence<OUString> aSeqLang; + if (aLangStatus >>= aSeqLang) + { + if (aSeqLang.getLength() == 4) + { + sCurrent = aSeqLang[0]; + eScriptType = static_cast<SvtScriptType>(aSeqLang[1].toInt32()); + sKeyboard = aSeqLang[1]; + sGuessText = aSeqLang[2]; + } + } + else + { + aLangStatus >>= sCurrent; + } LanguageType nLangType; std::set<LanguageType> aLangItems; - SvtScriptType eScriptType = static_cast<SvtScriptType>(aSeqLang[1].toInt32()); - if (!aSeqLang[0].isEmpty()) + if (!sCurrent.isEmpty()) { - nLangType = SvtLanguageTable::GetLanguageType(aSeqLang[0]); + nLangType = SvtLanguageTable::GetLanguageType(sCurrent); if (nLangType != LANGUAGE_DONTKNOW) { aLangItems.insert(nLangType); @@ -5430,9 +5442,9 @@ static void getDocLanguages(LibreOfficeKitDocument* pThis, uno::Sequence<lang::L aLangItems.insert(nLangType); } - if (!aSeqLang[2].isEmpty()) + if (!sKeyboard.isEmpty()) { - nLangType = SvtLanguageTable::GetLanguageType(aSeqLang[2]); + nLangType = SvtLanguageTable::GetLanguageType(sKeyboard); if (nLangType != LANGUAGE_DONTKNOW && (eScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType))) { @@ -5440,7 +5452,7 @@ static void getDocLanguages(LibreOfficeKitDocument* pThis, uno::Sequence<lang::L } } - if (!aSeqLang[3].isEmpty()) + if (!sGuessText.isEmpty()) { Reference<linguistic2::XLanguageGuessing> xLangGuesser; try @@ -5453,9 +5465,10 @@ static void getDocLanguages(LibreOfficeKitDocument* pThis, uno::Sequence<lang::L if (xLangGuesser.is()) { - lang::Locale aLocale = xLangGuesser->guessPrimaryLanguage(aSeqLang[3], 0, - aSeqLang[3].getLength()); - nLangType = LanguageTag(aLocale).makeFallback().getLanguageType(); + lang::Locale aLocale = xLangGuesser->guessPrimaryLanguage(sGuessText, 0, + sGuessText.getLength()); + LanguageTag aLanguageTag(aLocale); + nLangType = aLanguageTag.getLanguageType(false); if (nLangType != LANGUAGE_DONTKNOW && (eScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType))) { commit dabccba088e5f504a241ff0c6ba1ebd9f1f61dfe Author: Henry Castro <hcas...@collabora.com> AuthorDate: Wed Jan 11 16:14:57 2023 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:45 2023 -0400 lok: add function getDocLanguages If the spell checker is disabled to use a remote spelling feature, the getLanguages function is obsolete. In order to not break stable functions, introduce the getDocLanguages for the remote spelling feature. Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: Ic210f31eddd3208b29d073ff35ba4fa2d98ea772 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145363 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Andras Timar <andras.ti...@collabora.com> (cherry picked from commit bb0c63cc73998a0f67ae4c3e59acea3827a6e11c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/146399 Tested-by: Jenkins diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 2d71b7b435d5..49a3a2f1a49e 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -73,6 +73,7 @@ #include <com/sun/star/document/MacroExecMode.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/document/XDocumentLanguages.hpp> #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/frame/DispatchResultEvent.hpp> #include <com/sun/star/frame/DispatchResultState.hpp> @@ -98,6 +99,7 @@ #include <com/sun/star/xml/crypto/XCertificateCreator.hpp> #include <com/sun/star/security/XCertificate.hpp> +#include <com/sun/star/linguistic2/LanguageGuessing.hpp> #include <com/sun/star/linguistic2/LinguServiceManager.hpp> #include <com/sun/star/linguistic2/XSpellChecker.hpp> #include <com/sun/star/i18n/LocaleCalendar2.hpp> @@ -5378,6 +5380,119 @@ static void doc_setGraphicSelection(LibreOfficeKitDocument* pThis, int nType, in pDoc->setGraphicSelection(nType, nX, nY); } +static void getDocLanguages(LibreOfficeKitDocument* pThis, uno::Sequence<lang::Locale>& rSeq) +{ + SfxViewFrame* pViewFrame = SfxViewFrame::Current(); + if (!pViewFrame) + return; + + SfxDispatcher* pDispatcher = pViewFrame->GetBindings().GetDispatcher(); + if (!pDispatcher) + return; + + css::uno::Any aLangStatus; + pDispatcher->QueryState(SID_LANGUAGE_STATUS, aLangStatus); + + Sequence<OUString> aSeqLang; + if (!(aLangStatus >>= aSeqLang)) + return; + + // (aSeqLang[0] == "Current Language", aSeqLang[1] == "Script Type", + // aSeqLang[2] == "Keyboard Language", aSeqLang[3] == "Guess Text Lang") + if (aSeqLang.getLength() != 4) + return; + + LanguageType nLangType; + std::set<LanguageType> aLangItems; + SvtScriptType eScriptType = static_cast<SvtScriptType>(aSeqLang[1].toInt32()); + + if (!aSeqLang[0].isEmpty()) + { + nLangType = SvtLanguageTable::GetLanguageType(aSeqLang[0]); + if (nLangType != LANGUAGE_DONTKNOW) + { + aLangItems.insert(nLangType); + } + } + + const AllSettings& rAllSettings = Application::GetSettings(); + nLangType = rAllSettings.GetLanguageTag().getLanguageType(); + if (nLangType != LANGUAGE_DONTKNOW && + (eScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType))) + { + aLangItems.insert(nLangType); + } + + nLangType = rAllSettings.GetUILanguageTag().getLanguageType(); + if (nLangType != LANGUAGE_DONTKNOW && + (eScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType))) + { + aLangItems.insert(nLangType); + } + + if (!aSeqLang[2].isEmpty()) + { + nLangType = SvtLanguageTable::GetLanguageType(aSeqLang[2]); + if (nLangType != LANGUAGE_DONTKNOW && + (eScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType))) + { + aLangItems.insert(nLangType); + } + } + + if (!aSeqLang[3].isEmpty()) + { + Reference<linguistic2::XLanguageGuessing> xLangGuesser; + try + { + xLangGuesser = linguistic2::LanguageGuessing::create(xContext); + } + catch(...) + { + } + + if (xLangGuesser.is()) + { + lang::Locale aLocale = xLangGuesser->guessPrimaryLanguage(aSeqLang[3], 0, + aSeqLang[3].getLength()); + nLangType = LanguageTag(aLocale).makeFallback().getLanguageType(); + if (nLangType != LANGUAGE_DONTKNOW && + (eScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType))) + { + aLangItems.insert(nLangType); + } + } + } + + LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis); + Reference<document::XDocumentLanguages> xDocumentLanguages(pDocument->mxComponent, UNO_QUERY); + if (xDocumentLanguages.is()) + { + const Sequence<lang::Locale> aLocales(xDocumentLanguages->getDocumentLanguages( + static_cast<sal_Int16>(eScriptType), 64)); + + for (const lang::Locale& aLocale : aLocales) + { + nLangType = SvtLanguageTable::GetLanguageType(aLocale.Language); + if (nLangType != LANGUAGE_DONTKNOW && + (eScriptType & SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType))) + { + aLangItems.insert(nLangType); + } + } + } + + int nLocale = 0; + Sequence<lang::Locale> aLocales(aLangItems.size()); + auto pLocales = aLocales.getArray(); + for (const LanguageType& itLang : aLangItems) + { + pLocales[nLocale++] = LanguageTag::convertToLocale(itLang); + } + + rSeq = aLocales; +} + static void doc_resetSelection(LibreOfficeKitDocument* pThis) { comphelper::ProfileZone aZone("doc_resetSelection"); @@ -5395,7 +5510,7 @@ static void doc_resetSelection(LibreOfficeKitDocument* pThis) pDoc->resetSelection(); } -static char* getLanguages(const char* pCommand) +static char* getLanguages(LibreOfficeKitDocument* pThis, const char* pCommand) { css::uno::Sequence< css::lang::Locale > aLocales; @@ -5408,6 +5523,16 @@ static char* getLanguages(const char* pCommand) if (xSpell.is()) aLocales = xSpell->getLocales(); } + + /* FIXME: To obtain the document languages the spell checker can be disabled, + so a future re-work of the getLanguages function is needed in favor to use + getDocLanguages */ + if (!aLocales.hasElements()) + { + uno::Sequence< css::lang::Locale > aSeq; + getDocLanguages(pThis, aSeq); + aLocales = aSeq; + } } boost::property_tree::ptree aTree; @@ -5764,7 +5889,7 @@ static char* doc_getCommandValues(LibreOfficeKitDocument* pThis, const char* pCo if (!strcmp(pCommand, ".uno:LanguageStatus")) { - return getLanguages(pCommand); + return getLanguages(pThis, pCommand); } else if (!strcmp(pCommand, ".uno:CharFontName")) { commit 44500d0beba79d7e565b1ed56152188a69960155 Author: Henry Castro <hcas...@collabora.com> AuthorDate: Fri Dec 23 13:57:01 2022 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:44 2023 -0400 lok: disable spell if remote language tool enabled . Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: I73158c3feaa84af4d713d3f1b1fc9a60dcf95463 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144785 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-by: Miklos Vajna <vmik...@collabora.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145601 Tested-by: Jenkins diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 43797b5b63c9..2d71b7b435d5 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -54,6 +54,8 @@ #include <rtl/bootstrap.hxx> #include <rtl/strbuf.hxx> #include <rtl/uri.hxx> +#include <svl/zforlist.hxx> +#include <linguistic/misc.hxx> #include <cppuhelper/bootstrap.hxx> #include <comphelper/base64.hxx> #include <comphelper/dispatchcommand.hxx> @@ -7063,6 +7065,23 @@ void setLanguageToolConfig() rLanguageOpts.setUsername(aUsername); rLanguageOpts.setApiKey(aApiKey); } + + 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(); + + for (int itLocale = 0; itLocale < aLocales.getLength(); itLocale++) + { + xLangSrv->setConfiguredServices(SN_SPELLCHECKER, aLocales[itLocale], aEmpty); + } + } + } } catch(uno::Exception const& rException) { commit 7fc55467456bac81dea0a1db816472ece064b198 Author: Henry Castro <hcas...@collabora.com> AuthorDate: Thu Nov 24 18:35:08 2022 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:44 2023 -0400 linguistic: add REST API protocol unit test Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: I4768f8bb5bfa572d222fa5610f95c99169e6e390 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143249 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145600 Tested-by: Jenkins diff --git a/linguistic/CppunitTest_linguistic_restprotocol.mk b/linguistic/CppunitTest_linguistic_restprotocol.mk new file mode 100644 index 000000000000..4e56286efe0d --- /dev/null +++ b/linguistic/CppunitTest_linguistic_restprotocol.mk @@ -0,0 +1,39 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,linguistic_restprotocol)) + +$(eval $(call gb_CppunitTest_add_exception_objects,linguistic_restprotocol, \ + linguistic/qa/restprotocol \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,linguistic_restprotocol, \ + comphelper \ + cppu \ + cppuhelper \ + sal \ + svt \ + utl \ + test \ + unotest \ +)) + +$(eval $(call gb_CppunitTest_use_api,linguistic_restprotocol,\ + udkapi \ + offapi \ + oovbaapi \ +)) + +$(eval $(call gb_CppunitTest_use_configuration,linguistic_restprotocol)) + +$(eval $(call gb_CppunitTest_use_ure,linguistic_restprotocol)) + +$(eval $(call gb_CppunitTest_use_rdb,linguistic_restprotocol,services)) + +# vim: set noet sw=4 ts=4: diff --git a/linguistic/Module_linguistic.mk b/linguistic/Module_linguistic.mk index 956c1bbc2e80..b5366b97e611 100644 --- a/linguistic/Module_linguistic.mk +++ b/linguistic/Module_linguistic.mk @@ -16,9 +16,16 @@ $(eval $(call gb_Module_add_targets,linguistic,\ #$(eval $(call gb_Module_add_check_targets,linguistic,\ #)) +ifeq ($(OS),LINUX) $(eval $(call gb_Module_add_subsequentcheck_targets,linguistic,\ JunitTest_linguistic_unoapi \ + CppunitTest_linguistic_restprotocol \ )) +else +$(eval $(call gb_Module_add_subsequentcheck_targets,linguistic,\ + JunitTest_linguistic_unoapi \ +)) +endif # was disabled in old build system # JunitTest_linguistic_complex \ diff --git a/linguistic/qa/restprotocol.cxx b/linguistic/qa/restprotocol.cxx new file mode 100644 index 000000000000..61c04185c757 --- /dev/null +++ b/linguistic/qa/restprotocol.cxx @@ -0,0 +1,181 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> + +#include <algorithm> +#include <cassert> +#include <cstring> + +#include <sal/log.hxx> +#include <rtl/ustrbuf.hxx> +#include <rtl/strbuf.hxx> +#include <osl/socket.hxx> +#include <osl/thread.hxx> +#include <svtools/languagetoolcfg.hxx> +#include <unotest/bootstrapfixturebase.hxx> + +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/connection/XAcceptor.hpp> +#include <com/sun/star/connection/XConnector.hpp> +#include <com/sun/star/linguistic2/XProofreader.hpp> +#include <com/sun/star/linguistic2/ProofreadingResult.hpp> + +using namespace ::com::sun::star::uno; + +namespace +{ +class MockServerThread : public ::osl::Thread +{ +public: + MockServerThread() + : m_aSocketAddr("localhost", 2022) + { + } + + virtual void SAL_CALL run() + { + if (m_aAcceptorSocket.acceptConnection(m_aStreamSocket) != osl_Socket_Ok) + { + return; + } + + sal_Int32 nReadBytes; + Sequence<sal_Int8> aBuffer(512); + sal_Int32 nTcpNoDelay = sal_Int32(true); + m_aStreamSocket.setOption(osl_Socket_OptionTcpNoDelay, &nTcpNoDelay, sizeof(nTcpNoDelay), + osl_Socket_LevelTcp); + + nReadBytes = m_aStreamSocket.recv(aBuffer.getArray(), aBuffer.getLength()); + if (nReadBytes) + { + std::string aText(reinterpret_cast<const char*>(aBuffer.getConstArray()), nReadBytes); + + if (aText.find("POST /api/check") == std::string::npos) + { + NotFound(); + } + else if (aText.find("Content-Type: application/json") == std::string::npos) + { + NotFound(); + } + else + { + ResponseOK(); + } + } + } + + void ResponseOK() + { + OString aResponse( + "HTTP/1.1 200 OK\r\n" + "Server: MockServer\r\n" + "Cache-Control: no-cache\r\n" + "Content-Type: application/json\r\n" + "\r\n" + "{\"check-positions\":[{\"offset\":15,\"length\":6,\"errorcode\":4711,\"type\":" + "\"orth\"," + "\"severity\":1,\"proposals\":[\"Entwurf\",\"Entw\u00fcrfe\"]}," + "{\"offset\":22,\"length\":3,\"errorcode\":8221,\"type\":\"orth\",\"severity\":1}]}"); + + m_aStreamSocket.write(aResponse.getStr(), aResponse.getLength()); + m_aStreamSocket.close(); + } + + void NotFound() + { + OString aResponse("HTTP/1.1 404 Not Found\r\n" + "Connection: Closed\r\n" + "\r\n"); + + m_aStreamSocket.write(aResponse.getStr(), aResponse.getLength()); + m_aStreamSocket.close(); + } + + void stop() + { + m_aAcceptorSocket.close(); + join(); + } + + void init() + { + m_aAcceptorSocket.setOption(osl_Socket_OptionReuseAddr, 1); + CPPUNIT_ASSERT(m_aAcceptorSocket.bind(m_aSocketAddr)); + CPPUNIT_ASSERT(m_aAcceptorSocket.listen()); + } + +private: + ::osl::SocketAddr m_aSocketAddr; + ::osl::AcceptorSocket m_aAcceptorSocket; + ::osl::StreamSocket m_aStreamSocket; +}; +} + +MockServerThread aMockServer; + +class TestRestProtocol : public test::BootstrapFixtureBase +{ +public: + virtual void setUp() override; + virtual void tearDown() override; + +private: + CPPUNIT_TEST_SUITE(TestRestProtocol); + CPPUNIT_TEST(testProofreading); + CPPUNIT_TEST_SUITE_END(); + + void testProofreading(); +}; + +void TestRestProtocol::testProofreading() +{ + css::lang::Locale aLocale("en", "US", ""); + Sequence<::com::sun::star::beans::PropertyValue> aProperties; + SvxLanguageToolOptions& rLanguageOpts = SvxLanguageToolOptions::Get(); + rLanguageOpts.setBaseURL("http://127.0.0.1:2022/api"); + rLanguageOpts.setUsername("hcastro"); + rLanguageOpts.setApiKey("hcvhcvhcv"); + rLanguageOpts.setEnabled(true); + rLanguageOpts.setSSLVerification(false); + rLanguageOpts.setRestProtocol("duden"); + CPPUNIT_ASSERT_EQUAL(OUString("duden"), rLanguageOpts.getRestProtocol()); + + Reference<::com::sun::star::linguistic2::XProofreader> xProofreader( + m_xSFactory->createInstance("com.sun.star.linguistic2.Proofreader"), UNO_QUERY); + CPPUNIT_ASSERT(xProofreader.is()); + + com::sun::star::linguistic2::ProofreadingResult aResult + = xProofreader->doProofreading("id", "ths is a tst", aLocale, 0, 0, aProperties); + + CPPUNIT_ASSERT_EQUAL(2, aResult.aErrors.getLength()); +} + +void TestRestProtocol::setUp() +{ + test::BootstrapFixtureBase::setUp(); + + aMockServer.init(); + aMockServer.create(); + osl::Thread::wait(std::chrono::seconds(1)); +} + +void TestRestProtocol::tearDown() +{ + aMockServer.stop(); + + test::BootstrapFixtureBase::tearDown(); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(TestRestProtocol); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ commit 38a91df12b75bdcb263535c84a62f4446168a4cf Author: Henry Castro <hcas...@collabora.com> AuthorDate: Tue Nov 22 11:39:45 2022 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:44 2023 -0400 lok: add Rest Protocol property Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: I7353e16dbf835684e5ce5963387359924352937b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143124 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145599 Tested-by: Jenkins diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index ea5f556d7f65..43797b5b63c9 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -7035,22 +7035,27 @@ void setLanguageToolConfig() { const char* pEnabled = ::getenv("LANGUAGETOOL_ENABLED"); const char* pBaseUrlString = ::getenv("LANGUAGETOOL_BASEURL"); - const char* pUsername = ::getenv("LANGUAGETOOL_USERNAME"); - const char* pApikey = ::getenv("LANGUAGETOOL_APIKEY"); - const char* pSSLVerification = ::getenv("LANGUAGETOOL_SSL_VERIFICATION"); + 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); OUString aSSLVerification = OStringToOUString(pSSLVerification, RTL_TEXTENCODING_UTF8); if (aEnabled != "true") return; OUString aBaseUrl = OStringToOUString(pBaseUrlString, RTL_TEXTENCODING_UTF8); + OUString aRestProtocol = OStringToOUString(pRestProtocol, RTL_TEXTENCODING_UTF8); try { SvxLanguageToolOptions& rLanguageOpts = SvxLanguageToolOptions::Get(); rLanguageOpts.setBaseURL(aBaseUrl); rLanguageOpts.setEnabled(true); rLanguageOpts.setSSLVerification(aSSLVerification == "true"); + rLanguageOpts.setRestProtocol(aRestProtocol); if (pUsername && pApikey) { OUString aUsername = OStringToOUString(pUsername, RTL_TEXTENCODING_UTF8); commit 34d5485bb00a9b0e5c52add5785e2c4fa6d72496 Author: Henry Castro <hcas...@collabora.com> AuthorDate: Mon Nov 21 21:38:40 2022 -0400 Commit: Henry Castro <hcas...@collabora.com> CommitDate: Mon Feb 6 16:33:43 2023 -0400 lingucomponent: implement custom parse response rest protocol Response: HTTP/1.1 200 OK Transfer encoding: chunked Content-Type: application/json { "hyphenation-positions":[ {"offset":15,"quality":0}, {"offset":20,"quality":1} ], }, "check-positions":[ {"offset":15,"length":6,"errorcode":4711,"type":"orth","severity":1,"propos als":["Entwurf","Entw\u00fcrfe"]}, {"offset":22,"length":3,"errorcode":8221,"type":"orth","severity":1} ] } Signed-off-by: Henry Castro <hcas...@collabora.com> Change-Id: I87228237f23306fb367edab1e21ce002aaf13f2c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143108 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/145598 Tested-by: Jenkins diff --git a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx index 12d39ef8af93..2f06e054a5bd 100644 --- a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx +++ b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.cxx @@ -62,7 +62,7 @@ namespace Sequence<PropertyValue> lcl_GetLineColorPropertyFromErrorId(const std::string& rErrorId) { Color aColor; - if (rErrorId == "TYPOS") + if (rErrorId == "TYPOS" || rErrorId == "orth") { aColor = COL_LIGHTRED; } @@ -261,13 +261,78 @@ ProofreadingResult SAL_CALL LanguageToolGrammarChecker::doProofreading( return xRes; } - parseProofreadingJSONResponse(xRes, response_body); + if (rLanguageOpts.getRestProtocol() == sDuden) + { + parseDudenResponse(xRes, response_body); + } + else + { + parseProofreadingJSONResponse(xRes, response_body); + } // cache the result mCachedResults.insert( std::pair<OUString, Sequence<SingleProofreadingError>>(aText, xRes.aErrors)); return xRes; } +void LanguageToolGrammarChecker::parseDudenResponse(ProofreadingResult& rResult, + std::string_view aJSONBody) +{ + size_t nSize; + int nProposalSize; + boost::property_tree::ptree aRoot; + std::stringstream aStream(aJSONBody.data()); + boost::property_tree::read_json(aStream, aRoot); + + const boost::optional<boost::property_tree::ptree&> aPositions + = aRoot.get_child_optional("check-positions"); + if (!aPositions || !(nSize = aPositions.get().size())) + { + return; + } + + Sequence<SingleProofreadingError> aChecks(nSize); + auto pChecks = aChecks.getArray(); + size_t nIndex1 = 0, nIndex2 = 0; + auto itPos = aPositions.get().begin(); + while (itPos != aPositions.get().end()) + { + const boost::property_tree::ptree& rTree = itPos->second; + const std::string sType = rTree.get<std::string>("type", ""); + const int nOffset = rTree.get<int>("offset", 0); + const int nLength = rTree.get<int>("length", 0); + + pChecks[nIndex1].nErrorStart = nOffset; + pChecks[nIndex1].nErrorLength = nLength; + pChecks[nIndex1].nErrorType = PROOFREADING_ERROR; + //pChecks[nIndex1].aShortComment = ?? + //pChecks[nIndex1].aFullComment = ?? + pChecks[nIndex1].aProperties = lcl_GetLineColorPropertyFromErrorId(sType); + + const boost::optional<const boost::property_tree::ptree&> aProposals + = rTree.get_child_optional("proposals"); + if (aProposals && (nProposalSize = aProposals.get().size())) + { + pChecks[nIndex1].aSuggestions.realloc(std::min(nProposalSize, MAX_SUGGESTIONS_SIZE)); + + nIndex2 = 0; + auto itProp = aProposals.get().begin(); + auto pSuggestions = pChecks[nIndex1].aSuggestions.getArray(); + while (itProp != aProposals.get().end() && nIndex2 < MAX_SUGGESTIONS_SIZE) + { + pSuggestions[nIndex2++] + = OStringToOUString(itProp->second.data(), RTL_TEXTENCODING_UTF8); + itProp++; + } + } + + nIndex1++; + itPos++; + } + + rResult.aErrors = aChecks; +} + /* rResult is both input and output aJSONBody is the response body from the HTTP Request to LanguageTool API diff --git a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx index c3b79c95a43c..adfbe121c981 100644 --- a/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx +++ b/lingucomponent/source/spellcheck/languagetool/languagetoolimp.hxx @@ -51,6 +51,8 @@ class LanguageToolGrammarChecker mCachedResults; LanguageToolGrammarChecker(const LanguageToolGrammarChecker&) = delete; LanguageToolGrammarChecker& operator=(const LanguageToolGrammarChecker&) = delete; + static void parseDudenResponse(css::linguistic2::ProofreadingResult& rResult, + std::string_view aJSONBody); static void parseProofreadingJSONResponse(css::linguistic2::ProofreadingResult& rResult, std::string_view aJSONBody); static std::string makeDudenHttpRequest(std::string_view aURL, HTTP_METHOD method,