LibreOffice Module sw (master) 1
acmplwrd.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 <tools/urlobj.hxx>
21#include <hintids.hxx>
22#include <acmplwrd.hxx>
23#include <doc.hxx>
24#include <pagedesc.hxx>
25#include <poolfmt.hxx>
26#include <calbck.hxx>
28#include <editeng/svxacorr.hxx>
29#include <osl/diagnose.h>
30
31#include <editeng/acorrcfg.hxx>
32#include <sfx2/docfile.hxx>
33#include <docsh.hxx>
34
35#include <cassert>
36#include <vector>
37
39{
42#if OSL_DEBUG_LEVEL > 0
44#endif
45public:
48 virtual ~SwAutoCompleteClient() override;
49
51
52 const SwDoc& GetDoc() const {return *m_pDoc;}
53#if OSL_DEBUG_LEVEL > 0
55#endif
56protected:
57 virtual void SwClientNotify(const SwModify&, const SfxHint&) override;
58};
59
61{
62 std::vector<SwAutoCompleteClient>
65public:
67 m_rAutoCompleteWord(rParent){}
68 void AddDocument(SwDoc& rDoc);
69 void RemoveDocument(const SwDoc& rDoc);
70};
71
74{
75#if OSL_DEBUG_LEVEL > 0
77#endif
78 std::vector<const SwDoc*> m_aSourceDocs;
79 public:
80 SwAutoCompleteString(const OUString& rStr, sal_Int32 nLen);
81
82 virtual ~SwAutoCompleteString() override;
83 void AddDocument(const SwDoc& rDoc);
84 //returns true if last document reference has been removed
85 bool RemoveDocument(const SwDoc& rDoc);
86#if OSL_DEBUG_LEVEL > 0
88#endif
89};
90#if OSL_DEBUG_LEVEL > 0
93#endif
94
96 m_pAutoCompleteWord(&rToTell),
97 m_pDoc(&rSwDoc)
98{
100#if OSL_DEBUG_LEVEL > 0
102#endif
103}
104
106 SwClient(),
107 m_pAutoCompleteWord(rClient.m_pAutoCompleteWord),
108 m_pDoc(rClient.m_pDoc)
109{
111#if OSL_DEBUG_LEVEL > 0
113#endif
114}
115
117{
118#if OSL_DEBUG_LEVEL > 0
120#else
121 (void) this;
122#endif
123}
124
126{
128 m_pDoc = rClient.m_pDoc;
130 return *this;
131}
132
134{
135 if (rHint.GetId() != SfxHintId::SwLegacyModify)
136 return;
137 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
138 switch(pLegacy->GetWhich())
139 {
141 case RES_OBJECTDYING:
144 }
145}
146
148{
149 if (std::any_of(m_aClientVector.begin(), m_aClientVector.end(),
150 [&rDoc](SwAutoCompleteClient& rClient) { return &rClient.GetDoc() == &rDoc; }))
151 return;
152 m_aClientVector.emplace_back(m_rAutoCompleteWord, rDoc);
153}
154
156{
157 auto aIt = std::find_if(m_aClientVector.begin(), m_aClientVector.end(),
158 [&rDoc](SwAutoCompleteClient& rClient) { return &rClient.GetDoc() == &rDoc; });
159 if (aIt != m_aClientVector.end())
160 m_aClientVector.erase(aIt);
161}
162
164 const OUString& rStr, sal_Int32 const nLen)
165 : editeng::IAutoCompleteString(rStr.copy(0, nLen))
166{
167#if OSL_DEBUG_LEVEL > 0
169#endif
170}
171
173{
174#if OSL_DEBUG_LEVEL > 0
176#else
177 (void) this;
178#endif
179}
180
182{
183 auto aIt = std::find(m_aSourceDocs.begin(), m_aSourceDocs.end(), &rDoc);
184 if (aIt != m_aSourceDocs.end())
185 return;
186 m_aSourceDocs.push_back(&rDoc);
187}
188
190{
191 auto aIt = std::find(m_aSourceDocs.begin(), m_aSourceDocs.end(), &rDoc);
192 if (aIt != m_aSourceDocs.end())
193 {
194 m_aSourceDocs.erase(aIt);
195 return m_aSourceDocs.empty();
196 }
197 return false;
198}
199
201 editeng::SortedAutoCompleteStrings::size_type nWords, sal_uInt16 nMWrdLen ):
203 m_nMaxCount( nWords ),
204 m_nMinWordLen( nMWrdLen ),
205 m_bLockWordList( false )
206{
207}
208
210{
211 m_WordList.DeleteAndDestroyAll(); // so the assertion below works
212#if OSL_DEBUG_LEVEL > 0
215 OSL_ENSURE(!nStrings && !nClients, "AutoComplete: clients or string count mismatch");
216#endif
217}
218
219bool SwAutoCompleteWord::InsertWord( const OUString& rWord, SwDoc& rDoc )
220{
221 SwDocShell* pDocShell = rDoc.GetDocShell();
222 SfxMedium* pMedium = pDocShell ? pDocShell->GetMedium() : nullptr;
223 // strings from help module should not be added
224 if( pMedium )
225 {
226 const INetURLObject& rURL = pMedium->GetURLObject();
227 if ( rURL.GetProtocol() == INetProtocol::VndSunStarHelp )
228 return false;
229 }
230
231 OUString aNewWord = rWord.replaceAll(OUStringChar(CH_TXTATR_INWORD), "")
232 .replaceAll(OUStringChar(CH_TXTATR_BREAKWORD), "");
233
234 m_pImpl->AddDocument(rDoc);
235 bool bRet = false;
236 sal_Int32 nWrdLen = aNewWord.getLength();
237 while( nWrdLen && '.' == aNewWord[ nWrdLen-1 ])
238 --nWrdLen;
239
240 if( !m_bLockWordList && nWrdLen >= m_nMinWordLen )
241 {
242 SwAutoCompleteString* pNew = new SwAutoCompleteString( aNewWord, nWrdLen );
243 pNew->AddDocument(rDoc);
244 std::pair<editeng::SortedAutoCompleteStrings::const_iterator, bool>
245 aInsPair = m_WordList.insert(pNew);
246
247 m_LookupTree.insert( aNewWord.subView(0, nWrdLen) );
248
249 if (aInsPair.second)
250 {
251 bRet = true;
252 if (m_aLRUList.size() >= m_nMaxCount)
253 {
254 // the last one needs to be removed
255 // so that there is space for the first one
256 SwAutoCompleteString* pDel = m_aLRUList.back();
257 m_aLRUList.pop_back();
258 m_WordList.erase(pDel);
259 delete pDel;
260 }
261 m_aLRUList.push_front(pNew);
262 }
263 else
264 {
265 delete pNew;
266 // then move "up"
267 pNew = static_cast<SwAutoCompleteString*>(*aInsPair.first);
268
269 // add the document to the already inserted string
270 pNew->AddDocument(rDoc);
271
272 // move pNew to the front of the LRU list
273 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pNew );
274 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
275 if ( m_aLRUList.begin() != it && m_aLRUList.end() != it )
276 {
277 m_aLRUList.erase( it );
278 m_aLRUList.push_front( pNew );
279 }
280 }
281 }
282 return bRet;
283}
284
286 editeng::SortedAutoCompleteStrings::size_type nNewMax )
287{
288 if( nNewMax < m_nMaxCount && m_aLRUList.size() > nNewMax )
289 {
290 // remove the trailing ones
291 SwAutoCompleteStringPtrDeque::size_type nLRUIndex = nNewMax-1;
292 while (nNewMax < m_WordList.size() && nLRUIndex < m_aLRUList.size())
293 {
294 auto it = m_WordList.find(m_aLRUList[nLRUIndex++]);
295 OSL_ENSURE( m_WordList.end() != it, "String not found" );
296 editeng::IAutoCompleteString *const pDel = *it;
297 m_WordList.erase(it);
298 delete pDel;
299 }
300 m_aLRUList.erase( m_aLRUList.begin() + nNewMax - 1, m_aLRUList.end() );
301 }
302 m_nMaxCount = nNewMax;
303}
304
306{
307 // Do you really want to remove all words that are less than the minWrdLen?
308 if( n < m_nMinWordLen )
309 {
310 for (size_t nPos = 0; nPos < m_WordList.size(); ++nPos)
311 if (m_WordList[ nPos ]->GetAutoCompleteString().getLength() < n)
312 {
313 SwAutoCompleteString *const pDel =
314 dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos]);
315 m_WordList.erase_at(nPos);
316
317 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
318 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
319 m_aLRUList.erase( it );
320 --nPos;
321 delete pDel;
322 }
323 }
324
326}
327
333bool SwAutoCompleteWord::GetWordsMatching(std::u16string_view aMatch, std::vector<OUString>& rWords) const
334{
335 assert(rWords.empty());
336 m_LookupTree.findSuggestions(aMatch, rWords);
337 return !rWords.empty();
338}
339
342{
343 size_t nMyLen = m_WordList.size(), nNewLen = rNewLst.size();
344 size_t nMyPos = 0, nNewPos = 0;
345
346 for( ; nMyPos < nMyLen && nNewPos < nNewLen; ++nMyPos, ++nNewPos )
347 {
348 const editeng::IAutoCompleteString * pStr = rNewLst[ nNewPos ];
349 while (m_WordList[nMyPos] != pStr)
350 {
351 SwAutoCompleteString *const pDel =
352 dynamic_cast<SwAutoCompleteString*>(m_WordList[nMyPos]);
353 m_WordList.erase_at(nMyPos);
354 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
355 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
356 m_aLRUList.erase( it );
357 delete pDel;
358 if( nMyPos >= --nMyLen )
359 break;
360 }
361 }
362 // remove the elements at the end of the array
363 if( nMyPos >= nMyLen )
364 return;
365
366 // clear LRU array first then delete the string object
367 for( ; nNewPos < nMyLen; ++nNewPos )
368 {
369 SwAutoCompleteString *const pDel =
370 dynamic_cast<SwAutoCompleteString*>(m_WordList[nNewPos]);
371 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
372 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
373 m_aLRUList.erase( it );
374 delete pDel;
375 }
376 // remove from array
377 m_WordList.erase(m_WordList.begin() + nMyPos,
378 m_WordList.begin() + nMyLen);
379}
380
382{
383 m_pImpl->RemoveDocument(rDoc);
384
386 const bool bDelete = !pACorr->GetSwFlags().bAutoCmpltKeepList;
387 for (size_t nPos = m_WordList.size(); nPos; nPos--)
388 {
389 SwAutoCompleteString *const pCurrent = dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos - 1]);
390 if(pCurrent && pCurrent->RemoveDocument(rDoc) && bDelete)
391 {
392 m_WordList.erase_at(nPos - 1);
393 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pCurrent );
394 OSL_ENSURE( m_aLRUList.end() != it, "word not found in LRU list" );
395 m_aLRUList.erase( it );
396 delete pCurrent;
397 }
398 }
399}
400
401/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
virtual SwPageDesc * GetPageDescFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return required automatic page style.
INetProtocol GetProtocol() const
SfxHintId GetId() const
const INetURLObject & GetURLObject() const
SfxMedium * GetMedium() const
SvxAutoCorrect * GetAutoCorrect()
static SvxAutoCorrCfg & Get()
SvxSwAutoFormatFlags & GetSwFlags()
virtual ~SwAutoCompleteClient() override
Definition: acmplwrd.cxx:116
SwAutoCompleteClient(SwAutoCompleteWord &rToTell, SwDoc &rSwDoc)
Definition: acmplwrd.cxx:95
const SwDoc & GetDoc() const
Definition: acmplwrd.cxx:52
static sal_uLong GetElementCount()
Definition: acmplwrd.cxx:54
static sal_uLong s_nSwAutoCompleteClientCount
Definition: acmplwrd.cxx:43
SwAutoCompleteClient & operator=(const SwAutoCompleteClient &rClient)
Definition: acmplwrd.cxx:125
SwAutoCompleteWord * m_pAutoCompleteWord
Definition: acmplwrd.cxx:40
virtual void SwClientNotify(const SwModify &, const SfxHint &) override
Definition: acmplwrd.cxx:133
static sal_uLong GetElementCount()
Definition: acmplwrd.cxx:87
static sal_uLong s_nSwAutoCompleteStringCount
Definition: acmplwrd.cxx:76
virtual ~SwAutoCompleteString() override
Definition: acmplwrd.cxx:172
SwAutoCompleteString(const OUString &rStr, sal_Int32 nLen)
Definition: acmplwrd.cxx:163
void AddDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:181
bool RemoveDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:189
std::vector< const SwDoc * > m_aSourceDocs
Definition: acmplwrd.cxx:78
void RemoveDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:155
SwAutoCompleteWord_Impl(SwAutoCompleteWord &rParent)
Definition: acmplwrd.cxx:66
void AddDocument(SwDoc &rDoc)
Definition: acmplwrd.cxx:147
std::vector< SwAutoCompleteClient > m_aClientVector
Definition: acmplwrd.cxx:63
SwAutoCompleteWord & m_rAutoCompleteWord
Definition: acmplwrd.cxx:64
editeng::SortedAutoCompleteStrings::size_type m_nMaxCount
Definition: acmplwrd.hxx:46
void SetMinWordLen(sal_uInt16 n)
Definition: acmplwrd.cxx:305
SwAutoCompleteWord(editeng::SortedAutoCompleteStrings::size_type nWords, sal_uInt16 nMWrdLen)
Definition: acmplwrd.cxx:200
void SetMaxCount(editeng::SortedAutoCompleteStrings::size_type n)
Definition: acmplwrd.cxx:285
void CheckChangedList(const editeng::SortedAutoCompleteStrings &rNewLst)
Definition: acmplwrd.cxx:340
editeng::SortedAutoCompleteStrings m_WordList
contains extended strings carrying source information
Definition: acmplwrd.hxx:41
bool InsertWord(const OUString &rWord, SwDoc &rDoc)
Definition: acmplwrd.cxx:219
editeng::Trie m_LookupTree
Definition: acmplwrd.hxx:42
bool GetWordsMatching(std::u16string_view aMatch, std::vector< OUString > &aWords) const
Return all words matching a given prefix.
Definition: acmplwrd.cxx:333
std::unique_ptr< SwAutoCompleteWord_Impl > m_pImpl
Definition: acmplwrd.hxx:45
void DocumentDying(const SwDoc &rDoc)
Definition: acmplwrd.cxx:381
SwAutoCompleteStringPtrDeque m_aLRUList
Definition: acmplwrd.hxx:43
sal_uInt16 m_nMinWordLen
Definition: acmplwrd.hxx:47
void EndListeningAll()
Definition: calbck.cxx:136
void StartListeningToSameModifyAs(const SwClient &)
Definition: calbck.cxx:128
Definition: doc.hxx:192
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:427
SwDocShell * GetDocShell()
Definition: doc.hxx:1355
void Add(SwClient *pDepend)
Definition: calbck.cxx:172
void insert(std::u16string_view sInputString) const
void findSuggestions(std::u16string_view sWordPart, std::vector< OUString > &rSuggestionList) const
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_REMOVE_UNO_OBJECT(181)
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_OBJECTDYING(RES_MSG_BEGIN)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:174
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:173
sal_Int64 n
sal_uInt16 nPos
double getLength(const B2DPolygon &rCandidate)
void copy(const fs::path &src, const fs::path &dest)
@ RES_POOLPAGE_STANDARD
Standard page.
Definition: poolfmt.hxx:170
sal_uIntPtr sal_uLong