1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef INCLUDED_EDITENG_SVXACORR_HXX
21 #define INCLUDED_EDITENG_SVXACORR_HXX
23 #include <o3tl/sorted_vector.hxx>
24 #include <o3tl/typed_flags_set.hxx>
25 #include <o3tl/string_view.hxx>
26 #include <i18nlangtag/languagetag.hxx>
27 #include <tools/time.hxx>
28 #include <tools/date.hxx>
29 #include <editeng/swafopt.hxx>
30 #include <editeng/editengdllapi.h>
31 #include <unotools/charclass.hxx>
36 #include <string_view>
43 namespace vcl
{ class Window
; }
44 namespace com::sun::star::embed
{ class XStorage
; }
45 namespace tools
{ template <typename T
> class SvRef
; }
47 struct CompareSvStringsISortDtor
49 bool operator()( std::u16string_view lhs
, std::u16string_view rhs
) const
51 return o3tl::compareToIgnoreAsciiCase( lhs
, rhs
) < 0;
55 class SvStringsISortDtor
56 : public o3tl::sorted_vector
<OUString
, CompareSvStringsISortDtor
>
61 enum class ACFlags
: sal_uInt32
{
63 CapitalStartSentence
= 0x00000001, // Capital letters at the beginning of a sentence
64 CapitalStartWord
= 0x00000002, // not two Capital letters at the beginning of a word
65 AddNonBrkSpace
= 0x00000004, // Add non breaking space before :,?!%
66 ChgOrdinalNumber
= 0x00000008, // Ordinal-Number 1st, 2nd,..
67 ChgToEnEmDash
= 0x00000010, // - -> Endash/Emdash
68 ChgWeightUnderl
= 0x00000020, // * -> Bold, _ -> Underscore
69 SetINetAttr
= 0x00000040, // Set INetAttribut
70 Autocorrect
= 0x00000080, // Call AutoCorrect
71 ChgQuotes
= 0x00000100, // replace double quotes
72 SaveWordCplSttLst
= 0x00000200, // Save Auto correction of Capital letter at beginning of sentence.
73 SaveWordWordStartLst
= 0x00000400, // Save Auto correction of TWo INitial CApitals or sMALL iNITIAL.
74 IgnoreDoubleSpace
= 0x00000800, // Ignore 2 Spaces
75 ChgSglQuotes
= 0x00001000, // Replace simple quotes
76 CorrectCapsLock
= 0x00002000, // Correct accidental use of cAPS LOCK key
77 TransliterateRTL
= 0x00004000, // Transliterate RTL text
78 ChgAngleQuotes
= 0x00008000, // >>, << -> angle quotes in some languages
79 SetDOIAttr
= 0x00010000, // Set DOIAttribute
81 ChgWordLstLoad
= 0x20000000, // Replacement list loaded
82 CplSttLstLoad
= 0x40000000, // Exception list for Capital letters Start loaded
83 WordStartLstLoad
= 0x80000000, // Exception list for Word Start loaded
86 template<> struct typed_flags
<ACFlags
> : is_typed_flags
<ACFlags
, 0xe001ffff> {};
98 // TODO: handle code points > U+FFFF and check users of this class
100 // only a mapping class
101 class EDITENG_DLLPUBLIC SvxAutoCorrDoc
104 virtual ~SvxAutoCorrDoc();
106 virtual bool Delete( sal_Int32 nStt
, sal_Int32 nEnd
) = 0;
107 virtual bool Insert( sal_Int32 nPos
, const OUString
& rTxt
) = 0;
108 virtual bool Replace( sal_Int32 nPos
, const OUString
& rTxt
) = 0;
109 virtual bool ReplaceRange( sal_Int32 nPos
, sal_Int32 nLen
, const OUString
& rTxt
) = 0;
111 virtual void SetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, sal_uInt16 nSlotId
,
114 virtual bool SetINetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, const OUString
& rURL
) = 0;
116 // Return the text of a previous paragraph.
117 // If no paragraph exits or just an empty one, then return an empty string.
118 // The flag indicates:
119 // TRUE: before the normal insertion position (TRUE)
120 // FALSE: in which the corrected word was inserted.
121 // (Does not to have to be the same paragraph !!!!)
122 virtual OUString
const* GetPrevPara(bool bAtNormalPos
) = 0;
124 virtual bool ChgAutoCorrWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
,
125 SvxAutoCorrect
& rACorrect
,
126 OUString
* pPara
) = 0;
127 virtual bool TransliterateRTLWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
,
128 bool bApply
= false ) = 0;
130 // Is called after the change of the signs by the functions
131 // - FnCapitalStartWord
132 // - FnCapitalStartSentence
133 // As an option, the words can then be inserted into the exception lists.
134 virtual void SaveCpltSttWord( ACFlags nFlag
, sal_Int32 nPos
,
135 const OUString
& rExceptWord
,
138 // which language at the position?
139 virtual LanguageType
GetLanguage( sal_Int32 nPos
) const;
143 class EDITENG_DLLPUBLIC SvxAutocorrWord
145 OUString sShort
, sLong
;
146 bool bIsTxtOnly
; // Is pure ASCII - Text
148 SvxAutocorrWord( OUString aS
, OUString aL
, bool bFlag
= true )
149 : sShort(std::move( aS
)), sLong(std::move( aL
)), bIsTxtOnly( bFlag
)
152 const OUString
& GetShort() const { return sShort
; }
153 const OUString
& GetLong() const { return sLong
; }
154 bool IsTextOnly() const { return bIsTxtOnly
; }
157 class EDITENG_DLLPUBLIC SvxAutocorrWordList
160 std::unique_ptr
<Impl
> mpImpl
;
162 SvxAutocorrWordList( const SvxAutocorrWordList
& ) = delete;
163 const SvxAutocorrWordList
& operator= ( const SvxAutocorrWordList
& ) = delete;
165 const SvxAutocorrWord
* WordMatches(const SvxAutocorrWord
*pFnd
,
166 std::u16string_view rTxt
,
168 sal_Int32 nEndPos
) const;
170 SvxAutocorrWordList();
171 // free any objects still in the set
172 ~SvxAutocorrWordList();
173 void DeleteAndDestroyAll();
174 const SvxAutocorrWord
* Insert(SvxAutocorrWord aWord
) const;
175 std::optional
<SvxAutocorrWord
> FindAndRemove(const SvxAutocorrWord
*pWord
);
176 void LoadEntry(const OUString
& sWrong
, const OUString
& sRight
, bool bOnlyTxt
);
179 struct CompareSvxAutocorrWordList
;
180 typedef std::vector
<SvxAutocorrWord
> AutocorrWordSetType
;
181 const AutocorrWordSetType
& getSortedContent() const;
183 const SvxAutocorrWord
* SearchWordsInList(std::u16string_view rTxt
, sal_Int32
& rStt
, sal_Int32 nEndPos
) const;
186 class EDITENG_DLLPUBLIC SvxAutoCorrectLanguageLists
188 OUString sShareAutoCorrFile
, sUserAutoCorrFile
;
189 // If the AutoCorr file is newer
191 tools::Time aModifiedTime
, aLastCheckTime
;
193 std::unique_ptr
<SvStringsISortDtor
> pCplStt_ExcptLst
;
194 std::unique_ptr
<SvStringsISortDtor
> pWordStart_ExcptLst
;
195 std::unique_ptr
<SvxAutocorrWordList
> pAutocorr_List
;
196 SvxAutoCorrect
& rAutoCorrect
;
200 bool IsFileChanged_Imp();
201 void LoadXMLExceptList_Imp( std::unique_ptr
<SvStringsISortDtor
>& rpLst
,
202 const OUString
& sStrmName
,
203 tools::SvRef
<SotStorage
>& rStg
);
204 static void SaveExceptList_Imp( const SvStringsISortDtor
& rLst
,
205 const OUString
& sStrmName
,
206 tools::SvRef
<SotStorage
> const & rStg
,
207 bool bConvert
= false);
209 bool MakeBlocklist_Imp( SotStorage
& rStg
);
210 void RemoveStream_Imp( const OUString
& rName
);
211 void MakeUserStorage_Impl();
214 SvxAutoCorrectLanguageLists( SvxAutoCorrect
& rParent
,
215 OUString aShareAutoCorrectFile
,
216 OUString aUserAutoCorrectFile
);
217 ~SvxAutoCorrectLanguageLists();
219 // Load, Set, Get - the replacement list
220 SvxAutocorrWordList
* LoadAutocorrWordList();
221 const SvxAutocorrWordList
* GetAutocorrWordList();
223 // Load, Set, Get - the exception list for Capital letter at the
224 // beginning of a sentence
225 SvStringsISortDtor
* LoadCplSttExceptList();
226 void SaveCplSttExceptList();
227 SvStringsISortDtor
* GetCplSttExceptList();
228 bool AddToCplSttExceptList(const OUString
& rNew
);
230 // Load, Set, Get the exception list for TWo INitial CApitals or sMALL iNITIAL
231 SvStringsISortDtor
* LoadWordStartExceptList();
232 void SaveWordStartExceptList();
233 SvStringsISortDtor
* GetWordStartExceptList();
234 bool AddToWordStartExceptList(const OUString
& rNew
);
236 // Save word substitutions:
237 // Store these directly in the storage. The word list is updated
240 bool PutText( const OUString
& rShort
, const OUString
& rLong
);
241 // - Text with attribution (only the SWG - SWG format!)
242 void PutText( const OUString
& rShort
, SfxObjectShell
& );
243 // - Make combined changes in one pass
244 bool MakeCombinedChanges( std::vector
<SvxAutocorrWord
>& aNewEntries
, std::vector
<SvxAutocorrWord
>& aDeleteEntries
);
247 class EDITENG_DLLPUBLIC SvxAutoCorrect
249 friend class SvxAutoCorrectLanguageLists
;
251 OUString sShareAutoCorrFile
, sUserAutoCorrFile
;
253 SvxSwAutoFormatFlags aSwFlags
; // StarWriter AutoFormat Flags
255 // all languages in a table
256 std::map
<LanguageTag
, SvxAutoCorrectLanguageLists
> m_aLangTable
;
257 std::map
<LanguageTag
, sal_Int64
> aLastFileTable
;
258 std::optional
<CharClass
> moCharClass
;
260 LanguageType eCharClassLang
;
263 sal_Unicode cStartDQuote
, cEndDQuote
, cStartSQuote
, cEndSQuote
;
267 SvxAutoCorrectLanguageLists
& GetLanguageList_( LanguageType eLang
);
269 void GetCharClass_( LanguageType eLang
);
272 // - Text with attribution (only the SWG - SWG format!)
273 // rShort is the stream name - encrypted!
274 virtual bool PutText( const css::uno::Reference
< css::embed::XStorage
>& rStg
,
275 const OUString
& rFileName
, const OUString
& rShort
, SfxObjectShell
&, OUString
& );
277 // required language in the table add if possible only when the file exists
278 bool CreateLanguageFile(const LanguageTag
& rLanguageTag
, bool bNewFile
= true);
279 // - Return the replacement text (only for SWG format, all others can be
280 // taken from the word list!)
281 // rShort is the stream name - encrypted!
284 sal_Unicode
GetQuote( sal_Unicode cInsChar
, bool bSttQuote
,
285 LanguageType eLang
) const;
286 virtual bool GetLongText( const OUString
& rShort
, OUString
& rLong
);
288 virtual void refreshBlockList( const css::uno::Reference
< css::embed::XStorage
>& rStg
);
290 SvxAutoCorrect( OUString aShareAutocorrFile
,
291 OUString aUserAutocorrFile
);
292 SvxAutoCorrect( const SvxAutoCorrect
& );
293 virtual ~SvxAutoCorrect();
295 /** Execute an AutoCorrect.
296 Returns what has been executed, according to the above auto correct flags.
297 @param io_bNbspRunNext
298 Remembers if a NO-BREAK SPACE was added (eg. in "fr" language)
299 (set to <TRUE/>) at the last character input that may have to
300 be removed again depending on what character is following.
302 // FIXME: this has the horrible flaw that the rTxt must be a reference
303 // to the actual SwTxtNode/EditNode string because it inserts the character
304 // in rDoc and expects that to side-effect rTxt
305 void DoAutoCorrect( SvxAutoCorrDoc
& rDoc
, const OUString
& rTxt
,
306 sal_Int32 nPos
, sal_Unicode cInsChar
, bool bInsert
, bool& io_bNbspRunNext
,
307 vcl::Window
const * pFrameWin
= nullptr );
309 // Return for the autotext expansion the previous word,
310 // AutoCorrect - corresponding algorithm
311 OUString
GetPrevAutoCorrWord(SvxAutoCorrDoc
const& rDoc
, const OUString
& rTxt
, sal_Int32 nPos
);
313 // Returns vector candidates for AutoText name match, starting with the longest string between
314 // 3 and 9 characters long, that is a chunk of text starting with a whitespace or with a word's
315 // first character, and ending at the current cursor position or empty string if no such string
317 static std::vector
<OUString
> GetChunkForAutoText(std::u16string_view rTxt
, sal_Int32 nPos
);
319 // Search for the words in the replacement table.
320 // rText - check in this text the words of the list
321 // rStt - the detected starting position
322 // nEnd - to check position - as of this item forward
323 // rLang - Input: in which language is searched
324 // Output: in which "language list" was it found
325 const SvxAutocorrWord
* SearchWordsInList( std::u16string_view rTxt
,
326 sal_Int32
& rStt
, sal_Int32 nEndPos
,
327 SvxAutoCorrDoc
& rDoc
,
328 LanguageTag
& rLang
);
330 // Query/Set the Character for the Quote substitution
331 sal_Unicode
GetStartSingleQuote() const { return cStartSQuote
; }
332 sal_Unicode
GetEndSingleQuote() const { return cEndSQuote
; }
333 sal_Unicode
GetStartDoubleQuote() const { return cStartDQuote
; }
334 sal_Unicode
GetEndDoubleQuote() const { return cEndDQuote
; }
336 void SetStartSingleQuote( const sal_Unicode cStart
) { cStartSQuote
= cStart
; }
337 void SetEndSingleQuote( const sal_Unicode cEnd
) { cEndSQuote
= cEnd
; }
338 void SetStartDoubleQuote( const sal_Unicode cStart
) { cStartDQuote
= cStart
; }
339 void SetEndDoubleQuote( const sal_Unicode cEnd
) { cEndDQuote
= cEnd
; }
341 OUString
GetQuote( SvxAutoCorrDoc
const & rDoc
, sal_Int32 nInsPos
,
342 sal_Unicode cInsChar
, bool bSttQuote
);
343 void InsertQuote( SvxAutoCorrDoc
& rDoc
, sal_Int32 nInsPos
,
344 sal_Unicode cInsChar
, bool bSttQuote
, bool bIns
,
345 LanguageType eLang
, ACQuotes eType
) const;
347 // Query/Set the name of the AutoCorrect file
348 // the default is "autocorr.dat"
349 OUString
GetAutoCorrFileName( const LanguageTag
& rLanguageTag
/* = LANGUAGE_SYSTEM */ ,
350 bool bNewFile
= false,
351 bool bTstUserExist
= false,
352 bool bUnlocalized
= false ) const;
354 // Query/Set the current settings of AutoCorrect
355 ACFlags
GetFlags() const { return nFlags
; }
356 SvxSwAutoFormatFlags
& GetSwFlags() { return aSwFlags
;}
357 const SvxSwAutoFormatFlags
& GetSwFlags() const { return aSwFlags
; }
358 bool IsAutoCorrFlag( ACFlags nFlag
) const
359 { return bool(nFlags
& nFlag
); }
360 void SetAutoCorrFlag( ACFlags nFlag
, bool bOn
= true );
362 // Load, Set, Get - the replacement list
363 SvxAutocorrWordList
* LoadAutocorrWordList( LanguageType eLang
)
364 { return GetLanguageList_( eLang
).LoadAutocorrWordList(); }
366 // Save word substitutions:
367 // Save these directly in the storage. The word list is updated
370 bool PutText( const OUString
& rShort
, const OUString
& rLong
, LanguageType eLang
);
371 // - Text with attribution (only in the SWG - SWG format!)
372 void PutText( const OUString
& rShort
, SfxObjectShell
& rShell
, LanguageType eLang
)
373 { GetLanguageList_( eLang
).PutText(rShort
, rShell
); }
375 void MakeCombinedChanges( std::vector
<SvxAutocorrWord
>& aNewEntries
,
376 std::vector
<SvxAutocorrWord
>& aDeleteEntries
,
377 LanguageType eLang
);
379 // Load, Set, Get - the exception list for capital letters at the
380 // beginning of a sentence
381 void SaveCplSttExceptList( LanguageType eLang
);
382 SvStringsISortDtor
* LoadCplSttExceptList(LanguageType eLang
)
383 { return GetLanguageList_( eLang
).LoadCplSttExceptList(); }
384 const SvStringsISortDtor
* GetCplSttExceptList( LanguageType eLang
)
385 { return GetLanguageList_( eLang
).GetCplSttExceptList(); }
387 // Adds a single word. The list will be immediately written to the file!
388 bool AddCplSttException( const OUString
& rNew
, LanguageType eLang
);
390 // Load, Set, Get the exception list for TWo INitial CApitals or sMALL iNITIAL
391 void SaveWordStartExceptList( LanguageType eLang
);
392 SvStringsISortDtor
* LoadWordStartExceptList( LanguageType eLang
)
393 { return GetLanguageList_( eLang
).LoadWordStartExceptList(); }
394 const SvStringsISortDtor
* GetWordStartExceptList( LanguageType eLang
)
395 { return GetLanguageList_( eLang
).GetWordStartExceptList(); }
396 // Adds a single word. The list will be immediately written to the file!
397 bool AddWordStartException( const OUString
& rNew
, LanguageType eLang
);
399 // Search through the Languages for the entry
400 bool FindInWordStartExceptList( LanguageType eLang
, const OUString
& sWord
);
401 bool FindInCplSttExceptList( LanguageType eLang
, const OUString
& sWord
,
402 bool bAbbreviation
= false);
404 // Methods for the auto-correction
405 void FnCapitalStartWord( SvxAutoCorrDoc
&, const OUString
&,
406 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
407 LanguageType eLang
);
408 bool FnChgOrdinalNumber( SvxAutoCorrDoc
&, const OUString
&,
409 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
410 LanguageType eLang
);
411 bool FnChgToEnEmDash( SvxAutoCorrDoc
&, const OUString
&,
412 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
413 LanguageType eLang
);
414 bool FnAddNonBrkSpace( SvxAutoCorrDoc
&, std::u16string_view
,
416 LanguageType eLang
, bool& io_bNbspRunNext
);
417 bool FnSetINetAttr( SvxAutoCorrDoc
&, const OUString
&,
418 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
419 LanguageType eLang
);
420 bool FnSetDOIAttr( SvxAutoCorrDoc
&, const OUString
&,
421 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
422 LanguageType eLang
);
423 bool FnChgWeightUnderl( SvxAutoCorrDoc
&, const OUString
&,
425 void FnCapitalStartSentence( SvxAutoCorrDoc
&, const OUString
&, bool bNormalPos
,
426 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
428 bool FnCorrectCapsLock( SvxAutoCorrDoc
&, const OUString
&,
429 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
430 LanguageType eLang
);
432 static ACFlags
GetDefaultFlags();
434 // returns sal_True for characters where the function
435 // 'SvxAutoCorrect::AutoCorrect' should be called.
436 // (used to avoid occasional 'collisions' with (Thai) input-sequence-checking)
437 static bool IsAutoCorrectChar( sal_Unicode cChar
);
439 static bool NeedsHardspaceAutocorr( sal_Unicode cChar
);
441 CharClass
& GetCharClass( LanguageType eLang
)
443 if( !moCharClass
|| eLang
!= eCharClassLang
)
444 GetCharClass_( eLang
);
451 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */