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 <i18nlangtag/languagetag.hxx>
26 #include <tools/time.hxx>
27 #include <tools/date.hxx>
28 #include <editeng/swafopt.hxx>
29 #include <editeng/editengdllapi.h>
34 #include <string_view>
41 namespace vcl
{ class Window
; }
42 namespace com::sun::star::embed
{ class XStorage
; }
43 namespace tools
{ template <typename T
> class SvRef
; }
45 struct CompareSvStringsISortDtor
47 bool operator()( OUString
const& lhs
, std::u16string_view rhs
) const
49 return lhs
.compareToIgnoreAsciiCase( rhs
) < 0;
53 class SvStringsISortDtor
54 : public o3tl::sorted_vector
<OUString
, CompareSvStringsISortDtor
>
59 enum class ACFlags
: sal_uInt32
{
61 CapitalStartSentence
= 0x00000001, // Capital letters at the beginning of a sentence
62 CapitalStartWord
= 0x00000002, // not two Capital letters at the beginning of a word
63 AddNonBrkSpace
= 0x00000004, // Add non breaking space before :,?!%
64 ChgOrdinalNumber
= 0x00000008, // Ordinal-Number 1st, 2nd,..
65 ChgToEnEmDash
= 0x00000010, // - -> Endash/Emdash
66 ChgWeightUnderl
= 0x00000020, // * -> Bold, _ -> Underscore
67 SetINetAttr
= 0x00000040, // Set INetAttribut
68 Autocorrect
= 0x00000080, // Call AutoCorrect
69 ChgQuotes
= 0x00000100, // replace double quotes
70 SaveWordCplSttLst
= 0x00000200, // Save Auto correction of Capital letter at beginning of sentence.
71 SaveWordWrdSttLst
= 0x00000400, // Save Auto correction of TWo INitial CApitals or sMALL iNITIAL.
72 IgnoreDoubleSpace
= 0x00000800, // Ignore 2 Spaces
73 ChgSglQuotes
= 0x00001000, // Replace simple quotes
74 CorrectCapsLock
= 0x00002000, // Correct accidental use of cAPS LOCK key
75 TransliterateRTL
= 0x00004000, // Transliterate RTL text
76 ChgAngleQuotes
= 0x00008000, // >>, << -> angle quotes in some languages
78 ChgWordLstLoad
= 0x20000000, // Replacement list loaded
79 CplSttLstLoad
= 0x40000000, // Exception list for Capital letters Start loaded
80 WrdSttLstLoad
= 0x80000000, // Exception list for Word Start loaded
83 template<> struct typed_flags
<ACFlags
> : is_typed_flags
<ACFlags
, 0xe000ffff> {};
95 // TODO: handle code points > U+FFFF and check users of this class
97 // only a mapping class
98 class EDITENG_DLLPUBLIC SvxAutoCorrDoc
102 virtual ~SvxAutoCorrDoc();
104 virtual bool Delete( sal_Int32 nStt
, sal_Int32 nEnd
) = 0;
105 virtual bool Insert( sal_Int32 nPos
, const OUString
& rTxt
) = 0;
106 virtual bool Replace( sal_Int32 nPos
, const OUString
& rTxt
) = 0;
107 virtual bool ReplaceRange( sal_Int32 nPos
, sal_Int32 nLen
, const OUString
& rTxt
) = 0;
109 virtual void SetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, sal_uInt16 nSlotId
,
112 virtual bool SetINetAttr( sal_Int32 nStt
, sal_Int32 nEnd
, const OUString
& rURL
) = 0;
114 // Return the text of a previous paragraph.
115 // If no paragraph exits or just an empty one, then return an empty string.
116 // The flag indicates:
117 // TRUE: before the normal insertion position (TRUE)
118 // FALSE: in which the corrected word was inserted.
119 // (Does not to have to be the same paragraph !!!!)
120 virtual OUString
const* GetPrevPara(bool bAtNormalPos
) = 0;
122 virtual bool ChgAutoCorrWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
,
123 SvxAutoCorrect
& rACorrect
,
124 OUString
* pPara
) = 0;
125 virtual bool TransliterateRTLWord( sal_Int32
& rSttPos
, sal_Int32 nEndPos
) = 0;
127 // Is called after the change of the signs by the functions
128 // - FnCapitalStartWord
129 // - FnCapitalStartSentence
130 // As an option, the words can then be inserted into the exception lists.
131 virtual void SaveCpltSttWord( ACFlags nFlag
, sal_Int32 nPos
,
132 const OUString
& rExceptWord
,
135 // which language at the position?
136 virtual LanguageType
GetLanguage( sal_Int32 nPos
) const;
140 class EDITENG_DLLPUBLIC SvxAutocorrWord
142 OUString sShort
, sLong
;
143 bool bIsTxtOnly
; // Is pure ASCII - Text
145 SvxAutocorrWord( const OUString
& rS
, const OUString
& rL
, bool bFlag
= true )
146 : sShort( rS
), sLong( rL
), bIsTxtOnly( bFlag
)
149 const OUString
& GetShort() const { return sShort
; }
150 const OUString
& GetLong() const { return sLong
; }
151 bool IsTextOnly() const { return bIsTxtOnly
; }
154 class EDITENG_DLLPUBLIC SvxAutocorrWordList
157 std::unique_ptr
<Impl
> mpImpl
;
159 SvxAutocorrWordList( const SvxAutocorrWordList
& ) = delete;
160 const SvxAutocorrWordList
& operator= ( const SvxAutocorrWordList
& ) = delete;
162 const SvxAutocorrWord
* WordMatches(const SvxAutocorrWord
*pFnd
,
163 const OUString
&rTxt
,
165 sal_Int32 nEndPos
) const;
167 SvxAutocorrWordList();
168 // free any objects still in the set
169 ~SvxAutocorrWordList();
170 void DeleteAndDestroyAll();
171 const SvxAutocorrWord
* Insert(SvxAutocorrWord aWord
) const;
172 std::optional
<SvxAutocorrWord
> FindAndRemove(const SvxAutocorrWord
*pWord
);
173 void LoadEntry(const OUString
& sWrong
, const OUString
& sRight
, bool bOnlyTxt
);
176 struct CompareSvxAutocorrWordList
;
177 typedef std::vector
<SvxAutocorrWord
> AutocorrWordSetType
;
178 const AutocorrWordSetType
& getSortedContent() const;
180 const SvxAutocorrWord
* SearchWordsInList(const OUString
& rTxt
, sal_Int32
& rStt
, sal_Int32 nEndPos
) const;
183 class EDITENG_DLLPUBLIC SvxAutoCorrectLanguageLists
185 OUString sShareAutoCorrFile
, sUserAutoCorrFile
;
186 // If the AutoCorr file is newer
188 tools::Time aModifiedTime
, aLastCheckTime
;
190 std::unique_ptr
<SvStringsISortDtor
> pCplStt_ExcptLst
;
191 std::unique_ptr
<SvStringsISortDtor
> pWrdStt_ExcptLst
;
192 std::unique_ptr
<SvxAutocorrWordList
> pAutocorr_List
;
193 SvxAutoCorrect
& rAutoCorrect
;
197 bool IsFileChanged_Imp();
198 void LoadXMLExceptList_Imp( std::unique_ptr
<SvStringsISortDtor
>& rpLst
,
199 const char* pStrmName
,
200 tools::SvRef
<SotStorage
>& rStg
);
201 static void SaveExceptList_Imp( const SvStringsISortDtor
& rLst
,
202 const char* pStrmName
,
203 tools::SvRef
<SotStorage
> const & rStg
,
204 bool bConvert
= false);
206 bool MakeBlocklist_Imp( SotStorage
& rStg
);
207 void RemoveStream_Imp( const OUString
& rName
);
208 void MakeUserStorage_Impl();
211 SvxAutoCorrectLanguageLists( SvxAutoCorrect
& rParent
,
212 const OUString
& rShareAutoCorrectFile
,
213 const OUString
& rUserAutoCorrectFile
);
214 ~SvxAutoCorrectLanguageLists();
216 // Load, Set, Get - the replacement list
217 SvxAutocorrWordList
* LoadAutocorrWordList();
218 const SvxAutocorrWordList
* GetAutocorrWordList();
220 // Load, Set, Get - the exception list for Capital letter at the
221 // beginning of a sentence
222 SvStringsISortDtor
* LoadCplSttExceptList();
223 void SaveCplSttExceptList();
224 SvStringsISortDtor
* GetCplSttExceptList();
225 bool AddToCplSttExceptList(const OUString
& rNew
);
227 // Load, Set, Get the exception list for TWo INitial CApitals or sMALL iNITIAL
228 SvStringsISortDtor
* LoadWrdSttExceptList();
229 void SaveWrdSttExceptList();
230 SvStringsISortDtor
* GetWrdSttExceptList();
231 bool AddToWrdSttExceptList(const OUString
& rNew
);
233 // Save word substitutions:
234 // Store these directly in the storage. The word list is updated
237 bool PutText( const OUString
& rShort
, const OUString
& rLong
);
238 // - Text with attribution (only the SWG - SWG format!)
239 void PutText( const OUString
& rShort
, SfxObjectShell
& );
240 // - Make combined changes in one pass
241 bool MakeCombinedChanges( std::vector
<SvxAutocorrWord
>& aNewEntries
, std::vector
<SvxAutocorrWord
>& aDeleteEntries
);
244 class EDITENG_DLLPUBLIC SvxAutoCorrect
246 friend class SvxAutoCorrectLanguageLists
;
248 OUString sShareAutoCorrFile
, sUserAutoCorrFile
;
250 SvxSwAutoFormatFlags aSwFlags
; // StarWriter AutoFormat Flags
252 // all languages in a table
253 std::map
<LanguageTag
, std::unique_ptr
<SvxAutoCorrectLanguageLists
>> m_aLangTable
;
254 std::map
<LanguageTag
, sal_Int64
> aLastFileTable
;
255 std::unique_ptr
<CharClass
> pCharClass
;
257 LanguageType eCharClassLang
;
260 sal_Unicode cStartDQuote
, cEndDQuote
, cStartSQuote
, cEndSQuote
;
264 SvxAutoCorrectLanguageLists
& GetLanguageList_( LanguageType eLang
);
266 void GetCharClass_( LanguageType eLang
);
269 // - Text with attribution (only the SWG - SWG format!)
270 // rShort is the stream name - encrypted!
271 virtual bool PutText( const css::uno::Reference
< css::embed::XStorage
>& rStg
,
272 const OUString
& rFileName
, const OUString
& rShort
, SfxObjectShell
&, OUString
& );
274 // required language in the table add if possible only when the file exists
275 bool CreateLanguageFile(const LanguageTag
& rLanguageTag
, bool bNewFile
= true);
276 // - Return the replacement text (only for SWG format, all others can be
277 // taken from the word list!)
278 // rShort is the stream name - encrypted!
281 sal_Unicode
GetQuote( sal_Unicode cInsChar
, bool bSttQuote
,
282 LanguageType eLang
) const;
283 virtual bool GetLongText( const OUString
& rShort
, OUString
& rLong
);
285 virtual void refreshBlockList( const css::uno::Reference
< css::embed::XStorage
>& rStg
);
287 SvxAutoCorrect( const OUString
& rShareAutocorrFile
,
288 const OUString
& rUserAutocorrFile
);
289 SvxAutoCorrect( const SvxAutoCorrect
& );
290 virtual ~SvxAutoCorrect();
292 /** Execute an AutoCorrect.
293 Returns what has been executed, according to the above auto correct flags.
294 @param io_bNbspRunNext
295 Remembers if a NO-BREAK SPACE was added (eg. in "fr" language)
296 (set to <TRUE/>) at the last character input that may have to
297 be removed again depending on what character is following.
299 // FIXME: this has the horrible flaw that the rTxt must be a reference
300 // to the actual SwTxtNode/EditNode string because it inserts the character
301 // in rDoc and expects that to side-effect rTxt
302 void DoAutoCorrect( SvxAutoCorrDoc
& rDoc
, const OUString
& rTxt
,
303 sal_Int32 nPos
, sal_Unicode cInsChar
, bool bInsert
, bool& io_bNbspRunNext
,
304 vcl::Window
const * pFrameWin
= nullptr );
306 // Return for the autotext expansion the previous word,
307 // AutoCorrect - corresponding algorithm
308 OUString
GetPrevAutoCorrWord(SvxAutoCorrDoc
const& rDoc
, const OUString
& rTxt
, sal_Int32 nPos
);
310 // Returns vector candidates for AutoText name match, starting with the longest string between
311 // 3 and 9 characters long, that is a chunk of text starting with a whitespace or with a word's
312 // first character, and ending at the current cursor position or empty string if no such string
314 static std::vector
<OUString
> GetChunkForAutoText(const OUString
& rTxt
, sal_Int32 nPos
);
316 // Search for the words in the replacement table.
317 // rText - check in this text the words of the list
318 // rStt - the detected starting position
319 // nEnd - to check position - as of this item forward
320 // rLang - Input: in which language is searched
321 // Output: in which "language list" was it found
322 const SvxAutocorrWord
* SearchWordsInList( const OUString
& rTxt
,
323 sal_Int32
& rStt
, sal_Int32 nEndPos
,
324 SvxAutoCorrDoc
& rDoc
,
325 LanguageTag
& rLang
);
327 // Query/Set the Character for the Quote substitution
328 sal_Unicode
GetStartSingleQuote() const { return cStartSQuote
; }
329 sal_Unicode
GetEndSingleQuote() const { return cEndSQuote
; }
330 sal_Unicode
GetStartDoubleQuote() const { return cStartDQuote
; }
331 sal_Unicode
GetEndDoubleQuote() const { return cEndDQuote
; }
333 void SetStartSingleQuote( const sal_Unicode cStart
) { cStartSQuote
= cStart
; }
334 void SetEndSingleQuote( const sal_Unicode cEnd
) { cEndSQuote
= cEnd
; }
335 void SetStartDoubleQuote( const sal_Unicode cStart
) { cStartDQuote
= cStart
; }
336 void SetEndDoubleQuote( const sal_Unicode cEnd
) { cEndDQuote
= cEnd
; }
338 OUString
GetQuote( SvxAutoCorrDoc
const & rDoc
, sal_Int32 nInsPos
,
339 sal_Unicode cInsChar
, bool bSttQuote
);
340 void InsertQuote( SvxAutoCorrDoc
& rDoc
, sal_Int32 nInsPos
,
341 sal_Unicode cInsChar
, bool bSttQuote
, bool bIns
,
342 LanguageType eLang
, ACQuotes eType
) const;
344 // Query/Set the name of the AutoCorrect file
345 // the default is "autocorr.dat"
346 OUString
GetAutoCorrFileName( const LanguageTag
& rLanguageTag
/* = LANGUAGE_SYSTEM */ ,
347 bool bNewFile
= false,
348 bool bTstUserExist
= false,
349 bool bUnlocalized
= false ) const;
351 // Query/Set the current settings of AutoCorrect
352 ACFlags
GetFlags() const { return nFlags
; }
353 SvxSwAutoFormatFlags
& GetSwFlags() { return aSwFlags
;}
354 const SvxSwAutoFormatFlags
& GetSwFlags() const { return aSwFlags
; }
355 bool IsAutoCorrFlag( ACFlags nFlag
) const
356 { return bool(nFlags
& nFlag
); }
357 void SetAutoCorrFlag( ACFlags nFlag
, bool bOn
= true );
359 // Load, Set, Get - the replacement list
360 SvxAutocorrWordList
* LoadAutocorrWordList( LanguageType eLang
)
361 { return GetLanguageList_( eLang
).LoadAutocorrWordList(); }
363 // Save word substitutions:
364 // Save these directly in the storage. The word list is updated
367 bool PutText( const OUString
& rShort
, const OUString
& rLong
, LanguageType eLang
);
368 // - Text with attribution (only in the SWG - SWG format!)
369 void PutText( const OUString
& rShort
, SfxObjectShell
& rShell
, LanguageType eLang
)
370 { GetLanguageList_( eLang
).PutText(rShort
, rShell
); }
372 void MakeCombinedChanges( std::vector
<SvxAutocorrWord
>& aNewEntries
,
373 std::vector
<SvxAutocorrWord
>& aDeleteEntries
,
374 LanguageType eLang
);
376 // Load, Set, Get - the exception list for capital letters at the
377 // beginning of a sentence
378 void SaveCplSttExceptList( LanguageType eLang
);
379 SvStringsISortDtor
* LoadCplSttExceptList(LanguageType eLang
)
380 { return GetLanguageList_( eLang
).LoadCplSttExceptList(); }
381 const SvStringsISortDtor
* GetCplSttExceptList( LanguageType eLang
)
382 { return GetLanguageList_( eLang
).GetCplSttExceptList(); }
384 // Adds a single word. The list will be immediately written to the file!
385 bool AddCplSttException( const OUString
& rNew
, LanguageType eLang
);
387 // Load, Set, Get the exception list for TWo INitial CApitals or sMALL iNITIAL
388 void SaveWrdSttExceptList( LanguageType eLang
);
389 SvStringsISortDtor
* LoadWrdSttExceptList( LanguageType eLang
)
390 { return GetLanguageList_( eLang
).LoadWrdSttExceptList(); }
391 const SvStringsISortDtor
* GetWrdSttExceptList( LanguageType eLang
)
392 { return GetLanguageList_( eLang
).GetWrdSttExceptList(); }
393 // Adds a single word. The list will be immediately written to the file!
394 bool AddWrtSttException( const OUString
& rNew
, LanguageType eLang
);
396 // Search through the Languages for the entry
397 bool FindInWrdSttExceptList( LanguageType eLang
, const OUString
& sWord
);
398 bool FindInCplSttExceptList( LanguageType eLang
, const OUString
& sWord
,
399 bool bAbbreviation
= false);
401 // Methods for the auto-correction
402 void FnCapitalStartWord( SvxAutoCorrDoc
&, const OUString
&,
403 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
404 LanguageType eLang
);
405 bool FnChgOrdinalNumber( SvxAutoCorrDoc
&, const OUString
&,
406 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
407 LanguageType eLang
);
408 bool FnChgToEnEmDash( SvxAutoCorrDoc
&, const OUString
&,
409 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
410 LanguageType eLang
);
411 bool FnAddNonBrkSpace( SvxAutoCorrDoc
&, const OUString
&,
413 LanguageType eLang
, bool& io_bNbspRunNext
);
414 bool FnSetINetAttr( SvxAutoCorrDoc
&, const OUString
&,
415 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
416 LanguageType eLang
);
417 bool FnChgWeightUnderl( SvxAutoCorrDoc
&, const OUString
&,
419 void FnCapitalStartSentence( SvxAutoCorrDoc
&, const OUString
&, bool bNormalPos
,
420 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
422 bool FnCorrectCapsLock( SvxAutoCorrDoc
&, const OUString
&,
423 sal_Int32 nSttPos
, sal_Int32 nEndPos
,
424 LanguageType eLang
);
426 static ACFlags
GetDefaultFlags();
428 // returns sal_True for characters where the function
429 // 'SvxAutoCorrect::AutoCorrect' should be called.
430 // (used to avoid occasional 'collisions' with (Thai) input-sequence-checking)
431 static bool IsAutoCorrectChar( sal_Unicode cChar
);
433 static bool NeedsHardspaceAutocorr( sal_Unicode cChar
);
435 CharClass
& GetCharClass( LanguageType eLang
)
437 if( !pCharClass
|| eLang
!= eCharClassLang
)
438 GetCharClass_( eLang
);
445 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */