diff options
Diffstat (limited to 'include/editeng/svxacorr.hxx')
-rw-r--r-- | include/editeng/svxacorr.hxx | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/include/editeng/svxacorr.hxx b/include/editeng/svxacorr.hxx new file mode 100644 index 000000000..7483e83c1 --- /dev/null +++ b/include/editeng/svxacorr.hxx @@ -0,0 +1,447 @@ +/* -*- 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/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#ifndef INCLUDED_EDITENG_SVXACORR_HXX +#define INCLUDED_EDITENG_SVXACORR_HXX + +#include <o3tl/sorted_vector.hxx> +#include <o3tl/typed_flags_set.hxx> +#include <o3tl/string_view.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <tools/time.hxx> +#include <tools/date.hxx> +#include <editeng/swafopt.hxx> +#include <editeng/editengdllapi.h> + +#include <optional> +#include <map> +#include <memory> +#include <string_view> +#include <utility> + +class CharClass; +class SfxPoolItem; +class SotStorage; +class SvxAutoCorrect; +class SfxObjectShell; +namespace vcl { class Window; } +namespace com::sun::star::embed { class XStorage; } +namespace tools { template <typename T> class SvRef; } + +struct CompareSvStringsISortDtor +{ + bool operator()( std::u16string_view lhs, std::u16string_view rhs ) const + { + return o3tl::compareToIgnoreAsciiCase( lhs, rhs ) < 0; + } +}; + +class SvStringsISortDtor + : public o3tl::sorted_vector<OUString, CompareSvStringsISortDtor> +{ +}; + +// Auto correct flags +enum class ACFlags : sal_uInt32 { + NONE = 0x00000000, + CapitalStartSentence = 0x00000001, // Capital letters at the beginning of a sentence + CapitalStartWord = 0x00000002, // not two Capital letters at the beginning of a word + AddNonBrkSpace = 0x00000004, // Add non breaking space before :,?!% + ChgOrdinalNumber = 0x00000008, // Ordinal-Number 1st, 2nd,.. + ChgToEnEmDash = 0x00000010, // - -> Endash/Emdash + ChgWeightUnderl = 0x00000020, // * -> Bold, _ -> Underscore + SetINetAttr = 0x00000040, // Set INetAttribut + Autocorrect = 0x00000080, // Call AutoCorrect + ChgQuotes = 0x00000100, // replace double quotes + SaveWordCplSttLst = 0x00000200, // Save Auto correction of Capital letter at beginning of sentence. + SaveWordWordStartLst = 0x00000400, // Save Auto correction of TWo INitial CApitals or sMALL iNITIAL. + IgnoreDoubleSpace = 0x00000800, // Ignore 2 Spaces + ChgSglQuotes = 0x00001000, // Replace simple quotes + CorrectCapsLock = 0x00002000, // Correct accidental use of cAPS LOCK key + TransliterateRTL = 0x00004000, // Transliterate RTL text + ChgAngleQuotes = 0x00008000, // >>, << -> angle quotes in some languages + + ChgWordLstLoad = 0x20000000, // Replacement list loaded + CplSttLstLoad = 0x40000000, // Exception list for Capital letters Start loaded + WordStartLstLoad = 0x80000000, // Exception list for Word Start loaded +}; +namespace o3tl { + template<> struct typed_flags<ACFlags> : is_typed_flags<ACFlags, 0xe000ffff> {}; +} + +enum class ACQuotes +{ + NONE, + NonBreakingSpace, + CapitalizeIAm, + DoubleAngleQuote, + UseApostrophe, +}; + +// TODO: handle code points > U+FFFF and check users of this class + +// only a mapping class +class EDITENG_DLLPUBLIC SvxAutoCorrDoc +{ +public: + virtual ~SvxAutoCorrDoc(); + + virtual bool Delete( sal_Int32 nStt, sal_Int32 nEnd ) = 0; + virtual bool Insert( sal_Int32 nPos, const OUString& rTxt ) = 0; + virtual bool Replace( sal_Int32 nPos, const OUString& rTxt ) = 0; + virtual bool ReplaceRange( sal_Int32 nPos, sal_Int32 nLen, const OUString& rTxt ) = 0; + + virtual void SetAttr( sal_Int32 nStt, sal_Int32 nEnd, sal_uInt16 nSlotId, + SfxPoolItem& ) = 0; + + virtual bool SetINetAttr( sal_Int32 nStt, sal_Int32 nEnd, const OUString& rURL ) = 0; + + // Return the text of a previous paragraph. + // If no paragraph exits or just an empty one, then return an empty string. + // The flag indicates: + // TRUE: before the normal insertion position (TRUE) + // FALSE: in which the corrected word was inserted. + // (Does not to have to be the same paragraph !!!!) + virtual OUString const* GetPrevPara(bool bAtNormalPos) = 0; + + virtual bool ChgAutoCorrWord( sal_Int32& rSttPos, sal_Int32 nEndPos, + SvxAutoCorrect& rACorrect, + OUString* pPara ) = 0; + virtual bool TransliterateRTLWord( sal_Int32& rSttPos, sal_Int32 nEndPos, + bool bApply = false ) = 0; + + // Is called after the change of the signs by the functions + // - FnCapitalStartWord + // - FnCapitalStartSentence + // As an option, the words can then be inserted into the exception lists. + virtual void SaveCpltSttWord( ACFlags nFlag, sal_Int32 nPos, + const OUString& rExceptWord, + sal_Unicode cChar ); + + // which language at the position? + virtual LanguageType GetLanguage( sal_Int32 nPos ) const; +}; + + +class EDITENG_DLLPUBLIC SvxAutocorrWord +{ + OUString sShort, sLong; + bool bIsTxtOnly; // Is pure ASCII - Text +public: + SvxAutocorrWord( OUString aS, OUString aL, bool bFlag = true ) + : sShort(std::move( aS )), sLong(std::move( aL )), bIsTxtOnly( bFlag ) + {} + + const OUString& GetShort() const { return sShort; } + const OUString& GetLong() const { return sLong; } + bool IsTextOnly() const { return bIsTxtOnly; } +}; + +class EDITENG_DLLPUBLIC SvxAutocorrWordList +{ + struct Impl; + std::unique_ptr<Impl> mpImpl; + + SvxAutocorrWordList( const SvxAutocorrWordList& ) = delete; + const SvxAutocorrWordList& operator= ( const SvxAutocorrWordList& ) = delete; + + const SvxAutocorrWord* WordMatches(const SvxAutocorrWord *pFnd, + const OUString &rTxt, + sal_Int32 &rStt, + sal_Int32 nEndPos) const; +public: + SvxAutocorrWordList(); + // free any objects still in the set + ~SvxAutocorrWordList(); + void DeleteAndDestroyAll(); + const SvxAutocorrWord* Insert(SvxAutocorrWord aWord) const; + std::optional<SvxAutocorrWord> FindAndRemove(const SvxAutocorrWord *pWord); + void LoadEntry(const OUString& sWrong, const OUString& sRight, bool bOnlyTxt); + bool empty() const; + + struct CompareSvxAutocorrWordList; + typedef std::vector<SvxAutocorrWord> AutocorrWordSetType; + const AutocorrWordSetType & getSortedContent() const; + + const SvxAutocorrWord* SearchWordsInList(const OUString& rTxt, sal_Int32& rStt, sal_Int32 nEndPos) const; +}; + +class EDITENG_DLLPUBLIC SvxAutoCorrectLanguageLists +{ + OUString sShareAutoCorrFile, sUserAutoCorrFile; + // If the AutoCorr file is newer + Date aModifiedDate; + tools::Time aModifiedTime, aLastCheckTime; + + std::unique_ptr<SvStringsISortDtor> pCplStt_ExcptLst; + std::unique_ptr<SvStringsISortDtor> pWordStart_ExcptLst; + std::unique_ptr<SvxAutocorrWordList> pAutocorr_List; + SvxAutoCorrect& rAutoCorrect; + + ACFlags nFlags; + + bool IsFileChanged_Imp(); + void LoadXMLExceptList_Imp( std::unique_ptr<SvStringsISortDtor>& rpLst, + const OUString& sStrmName, + tools::SvRef<SotStorage>& rStg); + static void SaveExceptList_Imp( const SvStringsISortDtor& rLst, + const OUString& sStrmName, + tools::SvRef<SotStorage> const & rStg, + bool bConvert = false); + + bool MakeBlocklist_Imp( SotStorage& rStg ); + void RemoveStream_Imp( const OUString& rName ); + void MakeUserStorage_Impl(); + +public: + SvxAutoCorrectLanguageLists( SvxAutoCorrect& rParent, + OUString aShareAutoCorrectFile, + OUString aUserAutoCorrectFile); + ~SvxAutoCorrectLanguageLists(); + + // Load, Set, Get - the replacement list + SvxAutocorrWordList* LoadAutocorrWordList(); + const SvxAutocorrWordList* GetAutocorrWordList(); + + // Load, Set, Get - the exception list for Capital letter at the + // beginning of a sentence + SvStringsISortDtor* LoadCplSttExceptList(); + void SaveCplSttExceptList(); + SvStringsISortDtor* GetCplSttExceptList(); + bool AddToCplSttExceptList(const OUString& rNew); + + // Load, Set, Get the exception list for TWo INitial CApitals or sMALL iNITIAL + SvStringsISortDtor* LoadWordStartExceptList(); + void SaveWordStartExceptList(); + SvStringsISortDtor* GetWordStartExceptList(); + bool AddToWordStartExceptList(const OUString& rNew); + + // Save word substitutions: + // Store these directly in the storage. The word list is updated + // accordingly! + // - pure Text + bool PutText( const OUString& rShort, const OUString& rLong ); + // - Text with attribution (only the SWG - SWG format!) + void PutText( const OUString& rShort, SfxObjectShell& ); + // - Make combined changes in one pass + bool MakeCombinedChanges( std::vector<SvxAutocorrWord>& aNewEntries, std::vector<SvxAutocorrWord>& aDeleteEntries ); +}; + +class EDITENG_DLLPUBLIC SvxAutoCorrect +{ + friend class SvxAutoCorrectLanguageLists; + + OUString sShareAutoCorrFile, sUserAutoCorrFile; + + SvxSwAutoFormatFlags aSwFlags; // StarWriter AutoFormat Flags + + // all languages in a table + std::map<LanguageTag, std::unique_ptr<SvxAutoCorrectLanguageLists>> m_aLangTable; + std::map<LanguageTag, sal_Int64> aLastFileTable; + std::unique_ptr<CharClass> pCharClass; + + LanguageType eCharClassLang; + + ACFlags nFlags; + sal_Unicode cStartDQuote, cEndDQuote, cStartSQuote, cEndSQuote; + + + // private methods + SvxAutoCorrectLanguageLists& GetLanguageList_( LanguageType eLang ); + + void GetCharClass_( LanguageType eLang ); + +protected: + // - Text with attribution (only the SWG - SWG format!) + // rShort is the stream name - encrypted! + virtual bool PutText( const css::uno::Reference < css::embed::XStorage >& rStg, + const OUString& rFileName, const OUString& rShort, SfxObjectShell&, OUString& ); + + // required language in the table add if possible only when the file exists + bool CreateLanguageFile(const LanguageTag& rLanguageTag, bool bNewFile = true); + // - Return the replacement text (only for SWG format, all others can be + // taken from the word list!) + // rShort is the stream name - encrypted! +public: + + sal_Unicode GetQuote( sal_Unicode cInsChar, bool bSttQuote, + LanguageType eLang ) const; + virtual bool GetLongText( const OUString& rShort, OUString& rLong ); + + virtual void refreshBlockList( const css::uno::Reference < css::embed::XStorage >& rStg); + + SvxAutoCorrect( OUString aShareAutocorrFile, + OUString aUserAutocorrFile ); + SvxAutoCorrect( const SvxAutoCorrect& ); + virtual ~SvxAutoCorrect(); + + /** Execute an AutoCorrect. + Returns what has been executed, according to the above auto correct flags. + @param io_bNbspRunNext + Remembers if a NO-BREAK SPACE was added (eg. in "fr" language) + (set to <TRUE/>) at the last character input that may have to + be removed again depending on what character is following. + */ + // FIXME: this has the horrible flaw that the rTxt must be a reference + // to the actual SwTxtNode/EditNode string because it inserts the character + // in rDoc and expects that to side-effect rTxt + void DoAutoCorrect( SvxAutoCorrDoc& rDoc, const OUString& rTxt, + sal_Int32 nPos, sal_Unicode cInsChar, bool bInsert, bool& io_bNbspRunNext, + vcl::Window const * pFrameWin = nullptr ); + + // Return for the autotext expansion the previous word, + // AutoCorrect - corresponding algorithm + OUString GetPrevAutoCorrWord(SvxAutoCorrDoc const& rDoc, const OUString& rTxt, sal_Int32 nPos); + + // Returns vector candidates for AutoText name match, starting with the longest string between + // 3 and 9 characters long, that is a chunk of text starting with a whitespace or with a word's + // first character, and ending at the current cursor position or empty string if no such string + // exists + static std::vector<OUString> GetChunkForAutoText(std::u16string_view rTxt, sal_Int32 nPos); + + // Search for the words in the replacement table. + // rText - check in this text the words of the list + // rStt - the detected starting position + // nEnd - to check position - as of this item forward + // rLang - Input: in which language is searched + // Output: in which "language list" was it found + const SvxAutocorrWord* SearchWordsInList( const OUString& rTxt, + sal_Int32& rStt, sal_Int32 nEndPos, + SvxAutoCorrDoc& rDoc, + LanguageTag& rLang ); + + // Query/Set the Character for the Quote substitution + sal_Unicode GetStartSingleQuote() const { return cStartSQuote; } + sal_Unicode GetEndSingleQuote() const { return cEndSQuote; } + sal_Unicode GetStartDoubleQuote() const { return cStartDQuote; } + sal_Unicode GetEndDoubleQuote() const { return cEndDQuote; } + + void SetStartSingleQuote( const sal_Unicode cStart ) { cStartSQuote = cStart; } + void SetEndSingleQuote( const sal_Unicode cEnd ) { cEndSQuote = cEnd; } + void SetStartDoubleQuote( const sal_Unicode cStart ) { cStartDQuote = cStart; } + void SetEndDoubleQuote( const sal_Unicode cEnd ) { cEndDQuote = cEnd; } + + OUString GetQuote( SvxAutoCorrDoc const & rDoc, sal_Int32 nInsPos, + sal_Unicode cInsChar, bool bSttQuote ); + void InsertQuote( SvxAutoCorrDoc& rDoc, sal_Int32 nInsPos, + sal_Unicode cInsChar, bool bSttQuote, bool bIns, + LanguageType eLang, ACQuotes eType ) const; + + // Query/Set the name of the AutoCorrect file + // the default is "autocorr.dat" + OUString GetAutoCorrFileName( const LanguageTag& rLanguageTag /* = LANGUAGE_SYSTEM */ , + bool bNewFile = false, + bool bTstUserExist = false, + bool bUnlocalized = false ) const; + + // Query/Set the current settings of AutoCorrect + ACFlags GetFlags() const { return nFlags; } + SvxSwAutoFormatFlags& GetSwFlags() { return aSwFlags;} + const SvxSwAutoFormatFlags& GetSwFlags() const { return aSwFlags; } + bool IsAutoCorrFlag( ACFlags nFlag ) const + { return bool(nFlags & nFlag); } + void SetAutoCorrFlag( ACFlags nFlag, bool bOn = true ); + + // Load, Set, Get - the replacement list + SvxAutocorrWordList* LoadAutocorrWordList( LanguageType eLang ) + { return GetLanguageList_( eLang ).LoadAutocorrWordList(); } + + // Save word substitutions: + // Save these directly in the storage. The word list is updated + // accordingly! + // - pure Text + bool PutText( const OUString& rShort, const OUString& rLong, LanguageType eLang ); + // - Text with attribution (only in the SWG - SWG format!) + void PutText( const OUString& rShort, SfxObjectShell& rShell, LanguageType eLang ) + { GetLanguageList_( eLang ).PutText(rShort, rShell ); } + + void MakeCombinedChanges( std::vector<SvxAutocorrWord>& aNewEntries, + std::vector<SvxAutocorrWord>& aDeleteEntries, + LanguageType eLang ); + + // Load, Set, Get - the exception list for capital letters at the + // beginning of a sentence + void SaveCplSttExceptList( LanguageType eLang ); + SvStringsISortDtor* LoadCplSttExceptList(LanguageType eLang) + { return GetLanguageList_( eLang ).LoadCplSttExceptList(); } + const SvStringsISortDtor* GetCplSttExceptList( LanguageType eLang ) + { return GetLanguageList_( eLang ).GetCplSttExceptList(); } + + // Adds a single word. The list will be immediately written to the file! + bool AddCplSttException( const OUString& rNew, LanguageType eLang ); + + // Load, Set, Get the exception list for TWo INitial CApitals or sMALL iNITIAL + void SaveWordStartExceptList( LanguageType eLang ); + SvStringsISortDtor* LoadWordStartExceptList( LanguageType eLang ) + { return GetLanguageList_( eLang ).LoadWordStartExceptList(); } + const SvStringsISortDtor* GetWordStartExceptList( LanguageType eLang ) + { return GetLanguageList_( eLang ).GetWordStartExceptList(); } + // Adds a single word. The list will be immediately written to the file! + bool AddWordStartException( const OUString& rNew, LanguageType eLang); + + // Search through the Languages for the entry + bool FindInWordStartExceptList( LanguageType eLang, const OUString& sWord ); + bool FindInCplSttExceptList( LanguageType eLang, const OUString& sWord, + bool bAbbreviation = false); + + // Methods for the auto-correction + void FnCapitalStartWord( SvxAutoCorrDoc&, const OUString&, + sal_Int32 nSttPos, sal_Int32 nEndPos, + LanguageType eLang ); + bool FnChgOrdinalNumber( SvxAutoCorrDoc&, const OUString&, + sal_Int32 nSttPos, sal_Int32 nEndPos, + LanguageType eLang ); + bool FnChgToEnEmDash( SvxAutoCorrDoc&, std::u16string_view, + sal_Int32 nSttPos, sal_Int32 nEndPos, + LanguageType eLang ); + bool FnAddNonBrkSpace( SvxAutoCorrDoc&, const OUString&, + sal_Int32 nEndPos, + LanguageType eLang, bool& io_bNbspRunNext ); + bool FnSetINetAttr( SvxAutoCorrDoc&, const OUString&, + sal_Int32 nSttPos, sal_Int32 nEndPos, + LanguageType eLang ); + bool FnChgWeightUnderl( SvxAutoCorrDoc&, const OUString&, + sal_Int32 nEndPos ); + void FnCapitalStartSentence( SvxAutoCorrDoc&, const OUString&, bool bNormalPos, + sal_Int32 nSttPos, sal_Int32 nEndPos, + LanguageType eLang); + bool FnCorrectCapsLock( SvxAutoCorrDoc&, const OUString&, + sal_Int32 nSttPos, sal_Int32 nEndPos, + LanguageType eLang ); + + static ACFlags GetDefaultFlags(); + +// returns sal_True for characters where the function +// 'SvxAutoCorrect::AutoCorrect' should be called. +// (used to avoid occasional 'collisions' with (Thai) input-sequence-checking) + static bool IsAutoCorrectChar( sal_Unicode cChar ); + + static bool NeedsHardspaceAutocorr( sal_Unicode cChar ); + + CharClass& GetCharClass( LanguageType eLang ) + { + if( !pCharClass || eLang != eCharClassLang ) + GetCharClass_( eLang ); + return *pCharClass; + } +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |