summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLászló Németh <nemeth@numbertext.org>2017-11-09 16:03:21 +0100
committerLászló Németh <nemeth@numbertext.org>2017-11-17 17:33:00 +0100
commit95d9f596336ebf19dc367f618b3788a4ce0ba542 (patch)
treed33140f4cc24c4f0fd5f46f165906e2908e857f7
parenta7ec994689f8ea5985f6c8f94f17a4417978ff41 (diff)
tdf#113739 add "Grammar By" feature to user dictionaries
Language-specific user dictionaries (en-US, de-DE, etc.) have got a new "Grammar By" field to specify optional automatic affixation and compounding of the new words by adding an example dictionary word. Test example: Create an en-US user dictionary. Add the new word "crowdfund" to it, also an example, the Hunspell en-US dictionary word "fund" in the optional "Grammar By" field. This way, the word "crowdfund" will be recognized by the spell checker with suffixes of the word "fund", too: crowdfund’s, crowdfunds, crowdfunder, crowdfunders and crowdfunding. Hunspell dictionaries with compound flag usage (German, Hungarian, etc.) can support automatic compounding of the new words, too. Change-Id: Id70dbee4544643967153f730ae64938e5cee0c82 Reviewed-on: https://gerrit.libreoffice.org/44562 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: László Németh <nemeth@numbertext.org>
-rw-r--r--cui/inc/strings.hrc1
-rw-r--r--cui/source/inc/optdict.hxx1
-rw-r--r--cui/source/options/optdict.cxx29
-rw-r--r--linguistic/source/dicimp.cxx36
4 files changed, 59 insertions, 8 deletions
diff --git a/cui/inc/strings.hrc b/cui/inc/strings.hrc
index 40270de92037..5909ef647c74 100644
--- a/cui/inc/strings.hrc
+++ b/cui/inc/strings.hrc
@@ -268,6 +268,7 @@
#define RID_SVXSTR_CHG_SMARTART NC_("RID_SVXSTR_CHG_SMARTART", "SmartArt to %PRODUCTNAME shapes or reverse")
#define RID_SVXSTR_OPT_DOUBLE_DICTS NC_("RID_SVXSTR_OPT_DOUBLE_DICTS", "The specified name already exists.\nPlease enter a new name.")
+#define RID_SVXSTR_OPT_GRAMMAR_BY NC_("RID_SVXSTR_OPT_GRAMMAR_BY", "~Grammar By")
#define STR_MODIFY NC_("STR_MODIFY", "~Replace")
#define RID_SVXSTR_CONFIRM_SET_LANGUAGE NC_("RID_SVXSTR_CONFIRM_SET_LANGUAGE", "Do you want to change the '%1' dictionary language?")
diff --git a/cui/source/inc/optdict.hxx b/cui/source/inc/optdict.hxx
index fb8cd6deb364..e2dc53bf9e6e 100644
--- a/cui/source/inc/optdict.hxx
+++ b/cui/source/inc/optdict.hxx
@@ -109,6 +109,7 @@ private:
OUString sModify;
OUString sNew;
+ OUString sReplaceFT_Text;
css::uno::Sequence<
css::uno::Reference<
diff --git a/cui/source/options/optdict.cxx b/cui/source/options/optdict.cxx
index c04584f08bb4..8b23f40c5445 100644
--- a/cui/source/options/optdict.cxx
+++ b/cui/source/options/optdict.cxx
@@ -227,6 +227,7 @@ SvxEditDictionaryDialog::SvxEditDictionaryDialog(
get(pWordED,"word");
get(pReplaceFT,"replace_label");
+ sReplaceFT_Text = pReplaceFT->GetText();
get(pReplaceED,"replace");
get(pWordsLB,"words");
pWordsLB->set_height_request(pWordsLB->GetTextHeight() * 8);
@@ -484,7 +485,22 @@ void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId )
pWordED->SetText(aStr);
pReplaceED->SetText(aStr);
- if(xDic->getDictionaryType() != DictionaryType_POSITIVE)
+ bool bIsNegative = xDic->getDictionaryType() != DictionaryType_POSITIVE;
+ bool bLangNone = LanguageTag(
+ xDic->getLocale() ).getLanguageType() == LANGUAGE_NONE;
+
+ // The label is "Replace By" only in negative dictionaries (forbidden
+ // words), otherwise "Grammar By" in language-specific dictionaries
+ // (where the optional second word is the sample word for
+ // the Hunspell based affixation/compounding of the new dictionary word)
+ if (bIsNegative)
+ {
+ pReplaceFT->SetText(sReplaceFT_Text);
+ } else if (!bLangNone) {
+ pReplaceFT->SetText(CuiResId(RID_SVXSTR_OPT_GRAMMAR_BY));
+ }
+
+ if(bIsNegative || !bLangNone)
{
nStaticTabs[0]=2;
@@ -525,7 +541,7 @@ void SvxEditDictionaryDialog::ShowWords_Impl( sal_uInt16 nId )
{
aStr = pEntry[i]->getDictionaryWord();
sal_uLong nPos = GetLBInsertPos( aStr );
- if(pEntry[i]->isNegative())
+ if(!pEntry[i]->getReplacementText().isEmpty())
{
aStr += "\t" + pEntry[i]->getReplacementText();
}
@@ -608,11 +624,10 @@ bool SvxEditDictionaryDialog::NewDelHdl(void const * pBtn)
{
// make changes in dic
- //! ...IsVisible should reflect whether the dictionary is a negativ
- //! or not (hopefully...)
- bool bIsNegEntry = pReplaceFT->IsVisible();
+ bool bIsNegEntry = xDic->getDictionaryType() == DictionaryType_NEGATIVE;
+
OUString aRplcText;
- if(bIsNegEntry)
+ if(!aReplaceStr.isEmpty())
aRplcText = aReplaceStr;
if (_pEntry) // entry selected in pWordsLB ie action = modify entry
@@ -635,7 +650,7 @@ bool SvxEditDictionaryDialog::NewDelHdl(void const * pBtn)
pWordsLB->SetUpdateMode(false);
sal_uLong _nPos = TREELIST_ENTRY_NOTFOUND;
- if(pReplaceFT->IsVisible())
+ if(!aReplaceStr.isEmpty())
{
sEntry += "\t" + aReplaceStr;
}
diff --git a/linguistic/source/dicimp.cxx b/linguistic/source/dicimp.cxx
index 1c985503c9f9..b5b1e840e94c 100644
--- a/linguistic/source/dicimp.cxx
+++ b/linguistic/source/dicimp.cxx
@@ -40,6 +40,9 @@
#include <com/sun/star/io/XInputStream.hpp>
#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/linguistic2/LinguServiceManager.hpp>
+#include <com/sun/star/linguistic2/XSpellChecker1.hpp>
+
#include "defs.hxx"
#include <algorithm>
@@ -59,6 +62,9 @@ using namespace linguistic;
#define MAX_HEADER_LENGTH 16
+// XML-header to query SPELLML support
+#define SPELLML_SUPPORT "<?xml?>"
+
static const sal_Char* const pVerStr2 = "WBSWG2";
static const sal_Char* const pVerStr5 = "WBSWG5";
static const sal_Char* const pVerStr6 = "WBSWG6";
@@ -70,6 +76,13 @@ static const sal_Int16 DIC_VERSION_5 = 5;
static const sal_Int16 DIC_VERSION_6 = 6;
static const sal_Int16 DIC_VERSION_7 = 7;
+static uno::Reference< XLinguServiceManager2 > GetLngSvcMgr_Impl()
+{
+ uno::Reference< XComponentContext > xContext( comphelper::getProcessComponentContext() );
+ uno::Reference< XLinguServiceManager2 > xRes = LinguServiceManager::create( xContext ) ;
+ return xRes;
+}
+
static bool getTag(const OString &rLine, const sal_Char *pTagName,
OString &rTagValue)
{
@@ -359,7 +372,7 @@ static OString formatForSave(const uno::Reference< XDictionaryEntry > &xEntry,
{
OStringBuffer aStr(OUStringToOString(xEntry->getDictionaryWord(), eEnc));
- if (xEntry->isNegative())
+ if (xEntry->isNegative() || !xEntry->getReplacementText().isEmpty())
{
aStr.append("==");
aStr.append(OUStringToOString(xEntry->getReplacementText(), eEnc));
@@ -672,6 +685,27 @@ bool DictionaryNeo::addEntry_Impl(const uno::Reference< XDictionaryEntry >& xDic
}
}
+ // add word to the Hunspell dictionary using a sample word for affixation/compounding
+ if (xDicEntry.is() && !xDicEntry->isNegative() && !xDicEntry->getReplacementText().isEmpty()) {
+ uno::Reference< XLinguServiceManager2 > xLngSvcMgr( GetLngSvcMgr_Impl() );
+ uno::Reference< XSpellChecker1 > xSpell;
+ Reference< XSpellAlternatives > xTmpRes;
+ xSpell.set( xLngSvcMgr->getSpellChecker(), UNO_QUERY );
+ Sequence< css::beans::PropertyValue > aEmptySeq;
+ if (xSpell.is() && (xSpell->isValid( SPELLML_SUPPORT, (sal_uInt16)nLanguage, aEmptySeq )))
+ {
+ // "Grammar By" sample word is a Hunspell dictionary word?
+ if (xSpell->isValid( xDicEntry->getReplacementText(), (sal_uInt16)nLanguage, aEmptySeq ))
+ {
+ xTmpRes = xSpell->spell( "<?xml?><query type='add'><word>" +
+ xDicEntry->getDictionaryWord() + "</word><word>" + xDicEntry->getReplacementText() +
+ "</word></query>", (sal_uInt16)nLanguage, aEmptySeq );
+ bRes = true;
+ } else
+ bRes = false;
+ }
+ }
+
return bRes;
}