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 <svl/listener.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 Notify(const SfxHint&) override;
58private:
59 void DocumentDying();
60};
61
63{
64 std::vector<SwAutoCompleteClient>
67public:
69 m_rAutoCompleteWord(rParent){}
70 void AddDocument(SwDoc& rDoc);
71 void RemoveDocument(const SwDoc& rDoc);
72};
73
76{
77#if OSL_DEBUG_LEVEL > 0
79#endif
80 std::vector<const SwDoc*> m_aSourceDocs;
81 public:
82 SwAutoCompleteString(const OUString& rStr, sal_Int32 nLen);
83
84 virtual ~SwAutoCompleteString() override;
85 void AddDocument(const SwDoc& rDoc);
86 //returns true if last document reference has been removed
87 bool RemoveDocument(const SwDoc& rDoc);
88#if OSL_DEBUG_LEVEL > 0
90#endif
91};
92#if OSL_DEBUG_LEVEL > 0
95#endif
96
98 m_pAutoCompleteWord(&rToTell),
99 m_pDoc(&rSwDoc)
100{
102#if OSL_DEBUG_LEVEL > 0
104#endif
105}
106
108 SvtListener(),
109 m_pAutoCompleteWord(rClient.m_pAutoCompleteWord),
110 m_pDoc(rClient.m_pDoc)
111{
113#if OSL_DEBUG_LEVEL > 0
115#endif
116}
117
119{
120#if OSL_DEBUG_LEVEL > 0
122#else
123 (void) this;
124#endif
125}
126
128{
130 m_pDoc = rClient.m_pDoc;
131 CopyAllBroadcasters(rClient);
132 return *this;
133}
134
136{
139}
140
142{
143 switch(rHint.GetId())
144 {
145 case SfxHintId::Dying:
147 return;
148 case SfxHintId::SwLegacyModify:
149 {
150 auto pLegacy = static_cast<const sw::LegacyModifyHint*>(&rHint);
151 switch(pLegacy->GetWhich())
152 {
154 case RES_OBJECTDYING:
156 return;
157 default:
158 return;
159 }
160 }
161 default:
162 return;
163 }
164}
165
167{
168 if (std::any_of(m_aClientVector.begin(), m_aClientVector.end(),
169 [&rDoc](SwAutoCompleteClient& rClient) { return &rClient.GetDoc() == &rDoc; }))
170 return;
171 m_aClientVector.emplace_back(m_rAutoCompleteWord, rDoc);
172}
173
175{
176 auto aIt = std::find_if(m_aClientVector.begin(), m_aClientVector.end(),
177 [&rDoc](SwAutoCompleteClient& rClient) { return &rClient.GetDoc() == &rDoc; });
178 if (aIt != m_aClientVector.end())
179 m_aClientVector.erase(aIt);
180}
181
183 const OUString& rStr, sal_Int32 const nLen)
184 : editeng::IAutoCompleteString(rStr.copy(0, nLen))
185{
186#if OSL_DEBUG_LEVEL > 0
188#endif
189}
190
192{
193#if OSL_DEBUG_LEVEL > 0
195#else
196 (void) this;
197#endif
198}
199
201{
202 auto aIt = std::find(m_aSourceDocs.begin(), m_aSourceDocs.end(), &rDoc);
203 if (aIt != m_aSourceDocs.end())
204 return;
205 m_aSourceDocs.push_back(&rDoc);
206}
207
209{
210 auto aIt = std::find(m_aSourceDocs.begin(), m_aSourceDocs.end(), &rDoc);
211 if (aIt != m_aSourceDocs.end())
212 {
213 m_aSourceDocs.erase(aIt);
214 return m_aSourceDocs.empty();
215 }
216 return false;
217}
218
220 editeng::SortedAutoCompleteStrings::size_type nWords, sal_uInt16 nMWrdLen ):
222 m_nMaxCount( nWords ),
223 m_nMinWordLen( nMWrdLen ),
224 m_bLockWordList( false )
225{
226}
227
229{
230 m_WordList.DeleteAndDestroyAll(); // so the assertion below works
231#if OSL_DEBUG_LEVEL > 0
234 OSL_ENSURE(!nStrings && !nClients, "AutoComplete: clients or string count mismatch");
235#endif
236}
237
238bool SwAutoCompleteWord::InsertWord( const OUString& rWord, SwDoc& rDoc )
239{
240 SwDocShell* pDocShell = rDoc.GetDocShell();
241 SfxMedium* pMedium = pDocShell ? pDocShell->GetMedium() : nullptr;
242 // strings from help module should not be added
243 if( pMedium )
244 {
245 const INetURLObject& rURL = pMedium->GetURLObject();
246 if ( rURL.GetProtocol() == INetProtocol::VndSunStarHelp )
247 return false;
248 }
249
250 OUString aNewWord = rWord.replaceAll(OUStringChar(CH_TXTATR_INWORD), "")
251 .replaceAll(OUStringChar(CH_TXTATR_BREAKWORD), "");
252
253 m_pImpl->AddDocument(rDoc);
254 bool bRet = false;
255 sal_Int32 nWrdLen = aNewWord.getLength();
256 while( nWrdLen && '.' == aNewWord[ nWrdLen-1 ])
257 --nWrdLen;
258
259 if( !m_bLockWordList && nWrdLen >= m_nMinWordLen )
260 {
261 SwAutoCompleteString* pNew = new SwAutoCompleteString( aNewWord, nWrdLen );
262 pNew->AddDocument(rDoc);
263 std::pair<editeng::SortedAutoCompleteStrings::const_iterator, bool>
264 aInsPair = m_WordList.insert(pNew);
265
266 m_LookupTree.insert( aNewWord.subView(0, nWrdLen) );
267
268 if (aInsPair.second)
269 {
270 bRet = true;
271 if (m_aLRUList.size() >= m_nMaxCount)
272 {
273 // the last one needs to be removed
274 // so that there is space for the first one
275 SwAutoCompleteString* pDel = m_aLRUList.back();
276 m_aLRUList.pop_back();
277 m_WordList.erase(pDel);
278 delete pDel;
279 }
280 m_aLRUList.push_front(pNew);
281 }
282 else
283 {
284 delete pNew;
285 // then move "up"
286 pNew = static_cast<SwAutoCompleteString*>(*aInsPair.first);
287
288 // add the document to the already inserted string
289 pNew->AddDocument(rDoc);
290
291 // move pNew to the front of the LRU list
292 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pNew );
293 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
294 if ( m_aLRUList.begin() != it && m_aLRUList.end() != it )
295 {
296 m_aLRUList.erase( it );
297 m_aLRUList.push_front( pNew );
298 }
299 }
300 }
301 return bRet;
302}
303
305 editeng::SortedAutoCompleteStrings::size_type nNewMax )
306{
307 if( nNewMax < m_nMaxCount && m_aLRUList.size() > nNewMax )
308 {
309 // remove the trailing ones
310 SwAutoCompleteStringPtrDeque::size_type nLRUIndex = nNewMax-1;
311 while (nNewMax < m_WordList.size() && nLRUIndex < m_aLRUList.size())
312 {
313 auto it = m_WordList.find(m_aLRUList[nLRUIndex++]);
314 OSL_ENSURE( m_WordList.end() != it, "String not found" );
315 editeng::IAutoCompleteString *const pDel = *it;
316 m_WordList.erase(it);
317 delete pDel;
318 }
319 m_aLRUList.erase( m_aLRUList.begin() + nNewMax - 1, m_aLRUList.end() );
320 }
321 m_nMaxCount = nNewMax;
322}
323
325{
326 // Do you really want to remove all words that are less than the minWrdLen?
327 if( n < m_nMinWordLen )
328 {
329 for (size_t nPos = 0; nPos < m_WordList.size(); ++nPos)
330 if (m_WordList[ nPos ]->GetAutoCompleteString().getLength() < n)
331 {
332 SwAutoCompleteString *const pDel =
333 dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos]);
334 m_WordList.erase_at(nPos);
335
336 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
337 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
338 m_aLRUList.erase( it );
339 --nPos;
340 delete pDel;
341 }
342 }
343
345}
346
352bool SwAutoCompleteWord::GetWordsMatching(std::u16string_view aMatch, std::vector<OUString>& rWords) const
353{
354 assert(rWords.empty());
355 m_LookupTree.findSuggestions(aMatch, rWords);
356 return !rWords.empty();
357}
358
361{
362 size_t nMyLen = m_WordList.size(), nNewLen = rNewLst.size();
363 size_t nMyPos = 0, nNewPos = 0;
364
365 for( ; nMyPos < nMyLen && nNewPos < nNewLen; ++nMyPos, ++nNewPos )
366 {
367 const editeng::IAutoCompleteString * pStr = rNewLst[ nNewPos ];
368 while (m_WordList[nMyPos] != pStr)
369 {
370 SwAutoCompleteString *const pDel =
371 dynamic_cast<SwAutoCompleteString*>(m_WordList[nMyPos]);
372 m_WordList.erase_at(nMyPos);
373 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
374 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
375 m_aLRUList.erase( it );
376 delete pDel;
377 if( nMyPos >= --nMyLen )
378 break;
379 }
380 }
381 // remove the elements at the end of the array
382 if( nMyPos >= nMyLen )
383 return;
384
385 // clear LRU array first then delete the string object
386 for( ; nNewPos < nMyLen; ++nNewPos )
387 {
388 SwAutoCompleteString *const pDel =
389 dynamic_cast<SwAutoCompleteString*>(m_WordList[nNewPos]);
390 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
391 OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
392 m_aLRUList.erase( it );
393 delete pDel;
394 }
395 // remove from array
396 m_WordList.erase(m_WordList.begin() + nMyPos,
397 m_WordList.begin() + nMyLen);
398}
399
401{
402 m_pImpl->RemoveDocument(rDoc);
403
405 const bool bDelete = !pACorr->GetSwFlags().bAutoCmpltKeepList;
406 for (size_t nPos = m_WordList.size(); nPos; nPos--)
407 {
408 SwAutoCompleteString *const pCurrent = dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos - 1]);
409 if(pCurrent && pCurrent->RemoveDocument(rDoc) && bDelete)
410 {
411 m_WordList.erase_at(nPos - 1);
412 SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pCurrent );
413 OSL_ENSURE( m_aLRUList.end() != it, "word not found in LRU list" );
414 m_aLRUList.erase( it );
415 delete pCurrent;
416 }
417 }
418}
419
420/* 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
void EndListeningAll()
void CopyAllBroadcasters(const SvtListener &r)
bool StartListening(SvtBroadcaster &rBroadcaster)
SvxAutoCorrect * GetAutoCorrect()
static SvxAutoCorrCfg & Get()
SvxSwAutoFormatFlags & GetSwFlags()
virtual void Notify(const SfxHint &) override
Definition: acmplwrd.cxx:141
virtual ~SwAutoCompleteClient() override
Definition: acmplwrd.cxx:118
SwAutoCompleteClient(SwAutoCompleteWord &rToTell, SwDoc &rSwDoc)
Definition: acmplwrd.cxx:97
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:127
SwAutoCompleteWord * m_pAutoCompleteWord
Definition: acmplwrd.cxx:40
static sal_uLong GetElementCount()
Definition: acmplwrd.cxx:89
static sal_uLong s_nSwAutoCompleteStringCount
Definition: acmplwrd.cxx:78
virtual ~SwAutoCompleteString() override
Definition: acmplwrd.cxx:191
SwAutoCompleteString(const OUString &rStr, sal_Int32 nLen)
Definition: acmplwrd.cxx:182
void AddDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:200
bool RemoveDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:208
std::vector< const SwDoc * > m_aSourceDocs
Definition: acmplwrd.cxx:80
void RemoveDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:174
SwAutoCompleteWord_Impl(SwAutoCompleteWord &rParent)
Definition: acmplwrd.cxx:68
void AddDocument(SwDoc &rDoc)
Definition: acmplwrd.cxx:166
std::vector< SwAutoCompleteClient > m_aClientVector
Definition: acmplwrd.cxx:65
SwAutoCompleteWord & m_rAutoCompleteWord
Definition: acmplwrd.cxx:66
editeng::SortedAutoCompleteStrings::size_type m_nMaxCount
Definition: acmplwrd.hxx:46
void SetMinWordLen(sal_uInt16 n)
Definition: acmplwrd.cxx:324
SwAutoCompleteWord(editeng::SortedAutoCompleteStrings::size_type nWords, sal_uInt16 nMWrdLen)
Definition: acmplwrd.cxx:219
void SetMaxCount(editeng::SortedAutoCompleteStrings::size_type n)
Definition: acmplwrd.cxx:304
void CheckChangedList(const editeng::SortedAutoCompleteStrings &rNewLst)
Definition: acmplwrd.cxx:359
editeng::SortedAutoCompleteStrings m_WordList
contains extended strings carrying source information
Definition: acmplwrd.hxx:41
bool InsertWord(const OUString &rWord, SwDoc &rDoc)
Definition: acmplwrd.cxx:238
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:352
std::unique_ptr< SwAutoCompleteWord_Impl > m_pImpl
Definition: acmplwrd.hxx:45
void DocumentDying(const SwDoc &rDoc)
Definition: acmplwrd.cxx:400
SwAutoCompleteStringPtrDeque m_aLRUList
Definition: acmplwrd.hxx:43
sal_uInt16 m_nMinWordLen
Definition: acmplwrd.hxx:47
Definition: doc.hxx:197
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:440
SwDocShell * GetDocShell()
Definition: doc.hxx:1370
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)
#define CH_TXTATR_INWORD
Definition: hintids.hxx:175
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_OBJECTDYING(RES_FORMAT_MSG_BEGIN)
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:174
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