LibreOffice Module editeng (master) 1
splwrap.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <config_wasm_strip.h>
21
22#include <rtl/ustring.hxx>
24#include <vcl/svapp.hxx>
25#include <vcl/weld.hxx>
26#include <svtools/langtab.hxx>
27
28#include <vcl/errinf.hxx>
29#include <editeng/unolingu.hxx>
30#include <com/sun/star/frame/XStorable.hpp>
31#include <com/sun/star/linguistic2/XLinguProperties.hpp>
32#include <com/sun/star/linguistic2/XSpellChecker1.hpp>
33#include <com/sun/star/linguistic2/XHyphenator.hpp>
34#include <com/sun/star/linguistic2/XSearchableDictionaryList.hpp>
35#include <com/sun/star/linguistic2/XDictionary.hpp>
36
37#include <editeng/svxenum.hxx>
38#include <editeng/splwrap.hxx>
39#include <editeng/edtdlg.hxx>
40#include <editeng/eerdll.hxx>
41#include <editeng/editrids.hrc>
42#include <editeng/editerr.hxx>
43
44#include <map>
45#include <memory>
46
47using namespace ::com::sun::star;
48using namespace ::com::sun::star::uno;
49using namespace ::com::sun::star::beans;
50using namespace ::com::sun::star::linguistic2;
51
52
53// misc functions ---------------------------------------------
54
55void SvxPrepareAutoCorrect( OUString &rOldText, std::u16string_view rNewText )
56{
57 // This function should be used to strip (or add) trailing '.' from
58 // the strings before passing them on to the autocorrect function in
59 // order that the autocorrect function will hopefully
60 // works properly with normal words and abbreviations (with trailing '.')
61 // independent of if they are at the end of the sentence or not.
62 //
63 // rOldText: text to be replaced
64 // rNewText: replacement text
65
66 sal_Int32 nOldLen = rOldText.getLength();
67 sal_Int32 nNewLen = rNewText.size();
68 if (nOldLen && nNewLen)
69 {
70 bool bOldHasDot = '.' == rOldText[ nOldLen - 1 ],
71 bNewHasDot = '.' == rNewText[ nNewLen - 1 ];
72 if (bOldHasDot && !bNewHasDot
73 /*this is: !(bOldHasDot && bNewHasDot) && bOldHasDot*/)
74 rOldText = rOldText.copy( 0, nOldLen - 1 );
75 }
76}
77
78#define SVX_LANG_NEED_CHECK 0
79#define SVX_LANG_OK 1
80#define SVX_LANG_MISSING 2
81#define SVX_LANG_MISSING_DO_WARN 3
82
83typedef std::map< LanguageType, sal_uInt16 > LangCheckState_map_t;
84
86{
87 static LangCheckState_map_t aLangCheckState;
88 return aLangCheckState;
89}
90
92{
93 // display message boxes for languages not available for
94 // spellchecking or hyphenation
96 for (auto const& elem : rLCS)
97 {
98 LanguageType nLang = elem.first;
99 sal_uInt16 nVal = elem.second;
100 sal_uInt16 nTmpSpell = nVal & 0x00FF;
101 sal_uInt16 nTmpHyph = (nVal >> 8) & 0x00FF;
102
103 if (SVX_LANG_MISSING_DO_WARN == nTmpSpell)
104 {
105 OUString aErr( SvtLanguageTable::GetLanguageString( nLang ) );
108 nTmpSpell = SVX_LANG_MISSING;
109 }
110 if (SVX_LANG_MISSING_DO_WARN == nTmpHyph)
111 {
112 OUString aErr( SvtLanguageTable::GetLanguageString( nLang ) );
115 nTmpHyph = SVX_LANG_MISSING;
116 }
117
118 rLCS[ nLang ] = (nTmpHyph << 8) | nTmpSpell;
119 }
120
121}
122
124{
125}
126
127/*--------------------------------------------------------------------
128 * Description: Constructor, the test sequence is determined
129 *
130 * !bStart && !bOtherCntnt: BODY_END, BODY_START, OTHER
131 * !bStart && bOtherCntnt: OTHER, BODY
132 * bStart && !bOtherCntnt: BODY_END, OTHER
133 * bStart && bOtherCntnt: OTHER
134 *
135 --------------------------------------------------------------------*/
136
138 const bool bStart, const bool bIsAllRight ) :
139
140 pWin ( pWn ),
141 bOtherCntnt ( false ),
142 bStartChk ( false ),
143 bRevAllowed ( true ),
144 bAllRight ( bIsAllRight )
145{
146 Reference< linguistic2::XLinguProperties > xProp( LinguMgr::GetLinguPropertySet() );
147 bool bWrapReverse = xProp.is() && xProp->getIsWrapReverse();
148 bReverse = bWrapReverse;
149 bStartDone = !bReverse && bStart;
150 bEndDone = bReverse && bStart;
151}
152
153
155 Reference< XHyphenator > const &xHyphenator,
156 const bool bStart, const bool bOther ) :
157 pWin ( pWn ),
158 xHyph ( xHyphenator ),
159 bOtherCntnt ( bOther ),
160 bReverse ( false ),
161 bStartDone ( bOther || bStart ),
162 bEndDone ( false ),
163 bStartChk ( bOther ),
164 bRevAllowed ( false ),
165 bAllRight ( true )
166{
167}
168
169
171 Reference< XSpellChecker1 > const & xSpell, LanguageType nLang)
172{
174
175 LangCheckState_map_t::iterator aIt( rLCS.find( nLang ) );
176 sal_uInt16 nVal = aIt == rLCS.end() ? SVX_LANG_NEED_CHECK : aIt->second;
177
178 if (aIt == rLCS.end())
179 rLCS[ nLang ] = nVal;
180
181 if (SVX_LANG_NEED_CHECK == (nVal & 0x00FF))
182 {
183 sal_uInt16 nTmpVal = SVX_LANG_MISSING_DO_WARN;
184 if (xSpell.is() && xSpell->hasLanguage( static_cast<sal_uInt16>(nLang) ))
185 nTmpVal = SVX_LANG_OK;
186 nVal &= 0xFF00;
187 nVal |= nTmpVal;
188
189 rLCS[ nLang ] = nVal;
190 }
191
192 return static_cast<sal_Int16>(nVal);
193}
194
196 Reference< XHyphenator > const & xHyph, LanguageType nLang)
197{
199
200 LangCheckState_map_t::iterator aIt( rLCS.find( nLang ) );
201 sal_uInt16 nVal = aIt == rLCS.end() ? 0 : aIt->second;
202
203 if (aIt == rLCS.end())
204 rLCS[ nLang ] = nVal;
205
206 if (SVX_LANG_NEED_CHECK == ((nVal >> 8) & 0x00FF))
207 {
208 sal_uInt16 nTmpVal = SVX_LANG_MISSING_DO_WARN;
209 if (xHyph.is() && xHyph->hasLocale( LanguageTag::convertToLocale( nLang ) ))
210 nTmpVal = SVX_LANG_OK;
211 nVal &= 0x00FF;
212 nVal |= nTmpVal << 8;
213
214 rLCS[ nLang ] = nVal;
215 }
216
217 return static_cast<sal_Int16>(nVal);
218}
219
220
222{ // Here, the necessary preparations be made for SpellContinue in the
223} // given area.
224
225
227{
228 return false; // Should additional documents be examined?
229}
230
231
233{ // Area is complete, tidy up if necessary
234
235 // display error for last language not found
237}
238
240{
241}
242
243void SvxSpellWrapper::ReplaceAll( const OUString & )
244{ // Replace Word from the Replace list
245}
246
247void SvxSpellWrapper::InsertHyphen( const sal_Int32 )
248{ // inserting and deleting Hyphen
249}
250
251// Testing of the document areas in the order specified by the flags
253{
254#if ENABLE_WASM_STRIP_HUNSPELL
255 return;
256#else
257 if ( bOtherCntnt )
258 {
259 bReverse = false;
261 }
262 else
263 {
266 }
267
268 if ( !FindSpellError() )
269 return;
270
271 Reference< XHyphenatedWord > xHyphWord( GetLast(), UNO_QUERY );
272
273 if (xHyphWord.is())
274 {
277 pWin,
278 xHyphWord->getWord(),
279 LanguageTag( xHyphWord->getLocale() ).getLanguageType(),
280 xHyph, this ));
281 pDlg->Execute();
282 }
283#endif
284}
285
286
287// Select the next area
288
289
291{
292 Reference< linguistic2::XLinguProperties > xProp( LinguMgr::GetLinguPropertySet() );
293 bool bWrapReverse = xProp.is() && xProp->getIsWrapReverse();
294 bool bActRev = bRevAllowed && bWrapReverse;
295
296 // bActRev is the direction after Spell checking, bReverse is the one
297 // at the beginning.
298 if( bActRev == bReverse )
299 { // No change of direction, thus is the
300 if( bStartChk ) // desired area ( bStartChk )
301 bStartDone = true; // completely processed.
302 else
303 bEndDone = true;
304 }
305 else if( bReverse == bStartChk ) //For a change of direction, an area can
306 { // be processed during certain circumstances
307 if( bStartChk ) // If the first part is spell checked in backwards
308 bEndDone = true; // and this is reversed in the process, then
309 else // then the end part is processed (and vice-versa).
310 bStartDone = true;
311 }
312
313 bReverse = bActRev;
314 if( bOtherCntnt && bStartDone && bEndDone ) // Document has been fully checked?
315 {
316 if ( SpellMore() ) // spell check another document?
317 {
318 bOtherCntnt = false;
322 return true;
323 }
324 return false;
325 }
326
327 bool bGoOn = false;
328
329 if ( bOtherCntnt )
330 {
331 bStartChk = false;
333 bGoOn = true;
334 }
335 else if ( bStartDone && bEndDone )
336 {
337 if ( SpellMore() ) // check another document?
338 {
339 bOtherCntnt = false;
343 return true;
344 }
345 }
346 else
347 {
348 // a BODY_area done, ask for the other BODY_area
349 xWait.reset();
350
351 TranslateId pResId = bReverse ? RID_SVXSTR_QUERY_BW_CONTINUE : RID_SVXSTR_QUERY_CONTINUE;
352 std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pWin,
353 VclMessageType::Question, VclButtonsType::YesNo,
354 EditResId(pResId)));
355 if (xBox->run() != RET_YES)
356 {
357 // sacrifice the other area if necessary ask for special area
358 xWait.reset(new weld::WaitObject(pWin));
359 bStartDone = bEndDone = true;
360 return SpellNext();
361 }
362 else
363 {
366 bGoOn = true;
367 }
368 xWait.reset(new weld::WaitObject(pWin));
369 }
370 return bGoOn;
371}
372
373
374Reference< XDictionary > SvxSpellWrapper::GetAllRightDic()
375{
376 Reference< XDictionary > xDic;
377
378 Reference< XSearchableDictionaryList > xDicList( LinguMgr::GetDictionaryList() );
379 if (xDicList.is())
380 {
381 Sequence< Reference< XDictionary > > aDics( xDicList->getDictionaries() );
382 const Reference< XDictionary > *pDic = aDics.getConstArray();
383 sal_Int32 nCount = aDics.getLength();
384
385 sal_Int32 i = 0;
386 while (!xDic.is() && i < nCount)
387 {
388 Reference< XDictionary > xTmp = pDic[i];
389 if (xTmp.is())
390 {
391 if ( xTmp->isActive() &&
392 xTmp->getDictionaryType() != DictionaryType_NEGATIVE &&
393 LanguageTag( xTmp->getLocale() ).getLanguageType() == LANGUAGE_NONE )
394 {
395 Reference< frame::XStorable > xStor( xTmp, UNO_QUERY );
396 if (xStor.is() && xStor->hasLocation() && !xStor->isReadonly())
397 {
398 xDic = xTmp;
399 }
400 }
401 }
402 ++i;
403 }
404
405 if (!xDic.is())
406 {
408 if (xDic.is())
409 xDic->setActive( true );
410 }
411 }
412
413 return xDic;
414}
415
416
418{
420
421 xWait.reset(new weld::WaitObject(pWin));
422 bool bSpell = true;
423
424 Reference< XDictionary > xAllRightDic;
425 if (IsAllRight())
426 xAllRightDic = GetAllRightDic();
427
428 while ( bSpell )
429 {
431
432 Reference< XSpellAlternatives > xAlt( GetLast(), UNO_QUERY );
433 Reference< XHyphenatedWord > xHyphWord( GetLast(), UNO_QUERY );
434
435 if (xAlt.is())
436 {
437 if (IsAllRight() && xAllRightDic.is())
438 {
439 xAllRightDic->add( xAlt->getWord(), false, OUString() );
440 }
441 else
442 {
443 // look up in ChangeAllList for misspelled word
444 Reference< XDictionary > xChangeAllList =
446 Reference< XDictionaryEntry > xEntry;
447 if (xChangeAllList.is())
448 xEntry = xChangeAllList->getEntry( xAlt->getWord() );
449
450 if (xEntry.is())
451 {
452 // replace word without asking
453 ReplaceAll( xEntry->getReplacementText() );
454 }
455 else
456 bSpell = false;
457 }
458 }
459 else if (xHyphWord.is())
460 bSpell = false;
461 else
462 {
463 SpellEnd();
464 bSpell = SpellNext();
465 }
466 }
467 xWait.reset();
468 return GetLast().is();
469}
470
471
472/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
virtual VclPtr< AbstractHyphenWordDialog > CreateHyphenWordDialog(weld::Widget *, const OUString &rWord, LanguageType nLang, css::uno::Reference< css::linguistic2::XHyphenator > &xHyphen, SvxSpellWrapper *pWrapper)=0
static EditAbstractDialogFactory * Create()
Definition: edtdlg.cxx:22
static DialogMask HandleError(ErrCode nId, weld::Window *pParent=nullptr, DialogMask nMask=DialogMask::MAX)
LanguageType getLanguageType(bool bResolveSystem=true) const
static css::lang::Locale convertToLocale(LanguageType nLangID, bool bResolveSystem=true)
static css::uno::Reference< css::linguistic2::XDictionary > GetChangeAllList()
Definition: unolingu.cxx:516
static css::uno::Reference< css::linguistic2::XSearchableDictionaryList > GetDictionaryList()
Definition: unolingu.cxx:493
static css::uno::Reference< css::linguistic2::XDictionary > GetStandardDic()
Definition: unolingu.cxx:503
static css::uno::Reference< css::linguistic2::XLinguProperties > GetLinguPropertySet()
Definition: unolingu.cxx:498
static OUString GetLanguageString(const LanguageType eType)
const css::uno::Reference< css::uno::XInterface > & GetLast() const
Definition: splwrap.hxx:97
void SpellDocument()
Definition: splwrap.cxx:252
SvxSpellWrapper(SvxSpellWrapper const &)=delete
virtual bool SpellMore()
Definition: splwrap.cxx:226
bool IsAllRight() const
Definition: splwrap.hxx:93
css::uno::Reference< css::linguistic2::XHyphenator > xHyph
Definition: splwrap.hxx:56
static void ShowLanguageErrors()
Definition: splwrap.cxx:91
static sal_Int16 CheckHyphLang(css::uno::Reference< css::linguistic2::XHyphenator >const &xHyph, LanguageType nLang)
Definition: splwrap.cxx:195
virtual ~SvxSpellWrapper()
Definition: splwrap.cxx:123
virtual void SpellContinue()
Definition: splwrap.cxx:239
virtual void SpellStart(SvxSpellArea eSpell)
Definition: splwrap.cxx:221
bool FindSpellError()
Definition: splwrap.cxx:417
virtual void ReplaceAll(const OUString &rNewText)
Definition: splwrap.cxx:243
bool bRevAllowed
Definition: splwrap.hxx:62
static css::uno::Reference< css::linguistic2::XDictionary > GetAllRightDic()
Definition: splwrap.cxx:374
static sal_Int16 CheckSpellLang(css::uno::Reference< css::linguistic2::XSpellChecker1 > const &xSpell, LanguageType nLang)
Definition: splwrap.cxx:170
weld::Widget * pWin
Definition: splwrap.hxx:51
std::unique_ptr< weld::WaitObject > xWait
Definition: splwrap.hxx:52
bool bOtherCntnt
Definition: splwrap.hxx:57
virtual void InsertHyphen(const sal_Int32 nPos)
Definition: splwrap.cxx:247
virtual void SpellEnd()
Definition: splwrap.cxx:232
EDITENG_DLLPRIVATE bool SpellNext()
Definition: splwrap.cxx:290
int nCount
#define ERRCODE_SVX_LINGU_LANGUAGENOTEXISTS
Definition: editerr.hxx:24
OUString EditResId(TranslateId aId)
Definition: eerdll.cxx:192
#define LANGUAGE_NONE
int i
static LangCheckState_map_t & GetLangCheckState()
Definition: splwrap.cxx:85
#define SVX_LANG_MISSING
Definition: splwrap.cxx:80
#define SVX_LANG_OK
Definition: splwrap.cxx:79
#define SVX_LANG_MISSING_DO_WARN
Definition: splwrap.cxx:81
std::map< LanguageType, sal_uInt16 > LangCheckState_map_t
Definition: splwrap.cxx:83
void SvxPrepareAutoCorrect(OUString &rOldText, std::u16string_view rNewText)
Definition: splwrap.cxx:55
#define SVX_LANG_NEED_CHECK
Definition: splwrap.cxx:78
SvxSpellArea
Definition: svxenum.hxx:133
RET_YES