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 <hints.hxx>
23 #include <acmplwrd.hxx>
24 #include <doc.hxx>
25 #include <pagedesc.hxx>
26 #include <poolfmt.hxx>
27 #include <calbck.hxx>
29 #include <editeng/svxacorr.hxx>
30 #include <osl/diagnose.h>
31 
32 #include <editeng/acorrcfg.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <docsh.hxx>
35 
36 #include <cassert>
37 #include <vector>
38 
40 {
43 #if OSL_DEBUG_LEVEL > 0
45 #endif
46 public:
49  virtual ~SwAutoCompleteClient() override;
50 
52 
53  const SwDoc& GetDoc() const {return *m_pDoc;}
54 #if OSL_DEBUG_LEVEL > 0
56 #endif
57 protected:
58  virtual void Modify( const SfxPoolItem* pOld, const SfxPoolItem *pNew) override;
59 };
60 
62 {
63  std::vector<SwAutoCompleteClient>
66 public:
68  m_rAutoCompleteWord(rParent){}
69  void AddDocument(SwDoc& rDoc);
70  void RemoveDocument(const SwDoc& rDoc);
71 };
72 
75 {
76 #if OSL_DEBUG_LEVEL > 0
78 #endif
79  std::vector<const SwDoc*> m_aSourceDocs;
80  public:
81  SwAutoCompleteString(const OUString& rStr, sal_Int32 nLen);
82 
83  virtual ~SwAutoCompleteString() override;
84  void AddDocument(const SwDoc& rDoc);
85  //returns true if last document reference has been removed
86  bool RemoveDocument(const SwDoc& rDoc);
87 #if OSL_DEBUG_LEVEL > 0
89 #endif
90 };
91 #if OSL_DEBUG_LEVEL > 0
94 #endif
95 
97  m_pAutoCompleteWord(&rToTell),
98  m_pDoc(&rSwDoc)
99 {
101 #if OSL_DEBUG_LEVEL > 0
103 #endif
104 }
105 
107  SwClient(),
108  m_pAutoCompleteWord(rClient.m_pAutoCompleteWord),
109  m_pDoc(rClient.m_pDoc)
110 {
112 #if OSL_DEBUG_LEVEL > 0
114 #endif
115 }
116 
118 {
119 #if OSL_DEBUG_LEVEL > 0
121 #else
122  (void) this;
123 #endif
124 }
125 
127 {
129  m_pDoc = rClient.m_pDoc;
131  return *this;
132 }
133 
135 {
136  switch( pOld ? pOld->Which() : 0 )
137  {
139  case RES_OBJECTDYING:
140  if( static_cast<void*>(GetRegisteredIn()) == static_cast<const SwPtrMsgPoolItem *>(pOld)->pObject )
141  EndListeningAll();
143  break;
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 ):
202  m_pImpl(new SwAutoCompleteWord_Impl(*this)),
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 
219 bool 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.copy(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  editeng::SortedAutoCompleteStrings::const_iterator it =
295  m_WordList.find(m_aLRUList[ nLRUIndex++ ]);
296  OSL_ENSURE( m_WordList.end() != it, "String not found" );
297  editeng::IAutoCompleteString *const pDel = *it;
298  m_WordList.erase(it - m_WordList.begin());
299  delete pDel;
300  }
301  m_aLRUList.erase( m_aLRUList.begin() + nNewMax - 1, m_aLRUList.end() );
302  }
303  m_nMaxCount = nNewMax;
304 }
305 
307 {
308  // Do you really want to remove all words that are less than the minWrdLen?
309  if( n < m_nMinWordLen )
310  {
311  for (size_t nPos = 0; nPos < m_WordList.size(); ++nPos)
312  if (m_WordList[ nPos ]->GetAutoCompleteString().getLength() < n)
313  {
314  SwAutoCompleteString *const pDel =
315  dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos]);
316  m_WordList.erase(nPos);
317 
318  SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
319  OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
320  m_aLRUList.erase( it );
321  --nPos;
322  delete pDel;
323  }
324  }
325 
326  m_nMinWordLen = n;
327 }
328 
334 bool SwAutoCompleteWord::GetWordsMatching(const OUString& aMatch, std::vector<OUString>& rWords) const
335 {
336  assert(rWords.empty());
337  m_LookupTree.findSuggestions(aMatch, rWords);
338  return !rWords.empty();
339 }
340 
342  const editeng::SortedAutoCompleteStrings& rNewLst)
343 {
344  size_t nMyLen = m_WordList.size(), nNewLen = rNewLst.size();
345  size_t nMyPos = 0, nNewPos = 0;
346 
347  for( ; nMyPos < nMyLen && nNewPos < nNewLen; ++nMyPos, ++nNewPos )
348  {
349  const editeng::IAutoCompleteString * pStr = rNewLst[ nNewPos ];
350  while (m_WordList[nMyPos] != pStr)
351  {
352  SwAutoCompleteString *const pDel =
353  dynamic_cast<SwAutoCompleteString*>(m_WordList[nMyPos]);
354  m_WordList.erase(nMyPos);
355  SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
356  OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
357  m_aLRUList.erase( it );
358  delete pDel;
359  if( nMyPos >= --nMyLen )
360  break;
361  }
362  }
363  // remove the elements at the end of the array
364  if( nMyPos < nMyLen )
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 }
381 
383 {
384  m_pImpl->RemoveDocument(rDoc);
385 
387  const bool bDelete = !pACorr->GetSwFlags().bAutoCmpltKeepList;
388  for (size_t nPos = m_WordList.size(); nPos; nPos--)
389  {
390  SwAutoCompleteString *const pCurrent = dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos - 1]);
391  if(pCurrent && pCurrent->RemoveDocument(rDoc) && bDelete)
392  {
393  m_WordList.erase(nPos - 1);
394  SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pCurrent );
395  OSL_ENSURE( m_aLRUList.end() != it, "word not found in LRU list" );
396  m_aLRUList.erase( it );
397  delete pCurrent;
398  }
399  }
400 }
401 
402 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
bool InsertWord(const OUString &rWord, SwDoc &rDoc)
Definition: acmplwrd.cxx:219
void Add(SwClient *pDepend)
Definition: calbck.cxx:217
static SvxAutoCorrCfg & Get()
void DocumentDying(const SwDoc &rDoc)
Definition: acmplwrd.cxx:382
std::unique_ptr< SwAutoCompleteWord_Impl > m_pImpl
Definition: acmplwrd.hxx:45
SwDocShell * GetDocShell()
Definition: doc.hxx:1348
SwAutoCompleteString(const OUString &rStr, sal_Int32 nLen)
Definition: acmplwrd.cxx:163
void AddDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:181
static sal_uLong GetElementCount()
Definition: acmplwrd.cxx:88
sal_uIntPtr sal_uLong
SwAutoCompleteClient(SwAutoCompleteWord &rToTell, SwDoc &rSwDoc)
Definition: acmplwrd.cxx:96
Definition: doc.hxx:184
SwAutoCompleteWord * m_pAutoCompleteWord
Definition: acmplwrd.cxx:41
SwAutoCompleteWord(editeng::SortedAutoCompleteStrings::size_type nWords, sal_uInt16 nMWrdLen)
Definition: acmplwrd.cxx:200
editeng::SortedAutoCompleteStrings m_WordList
contains extended strings carrying source information
Definition: acmplwrd.hxx:41
EmbeddedObjectRef * pObject
SwDoc * m_pDoc
Definition: docbm.cxx:1190
void StartListeningToSameModifyAs(const SwClient &)
Definition: calbck.cxx:116
void findSuggestions(const OUString &sWordPart, std::vector< OUString > &rSuggestionList) const
#define CH_TXTATR_BREAKWORD
Definition: hintids.hxx:170
#define CH_TXTATR_INWORD
Definition: hintids.hxx:171
void insert(const OUString &sInputString) const
const BorderLinePrimitive2D *pCandidateB assert(pCandidateA)
IDocumentStylePoolAccess const & getIDocumentStylePoolAccess() const
Definition: doc.cxx:425
SvxSwAutoFormatFlags & GetSwFlags()
static sal_uLong s_nSwAutoCompleteClientCount
Definition: acmplwrd.cxx:44
SwAutoCompleteWord & m_rAutoCompleteWord
Definition: acmplwrd.cxx:65
virtual SwPageDesc * GetPageDescFromPool(sal_uInt16 nId, bool bRegardLanguage=true)=0
Return required automatic page style.
void EndListeningAll()
Definition: calbck.cxx:124
virtual ~SwAutoCompleteClient() override
Definition: acmplwrd.cxx:117
virtual void Modify(const SfxPoolItem *pOld, const SfxPoolItem *pNew) override
Definition: acmplwrd.cxx:134
void CheckChangedList(const editeng::SortedAutoCompleteStrings &rNewLst)
Definition: acmplwrd.cxx:341
bool GetWordsMatching(const OUString &aMatch, std::vector< OUString > &aWords) const
Return all words matching a given prefix.
Definition: acmplwrd.cxx:334
SwAutoCompleteStringPtrDeque m_aLRUList
Definition: acmplwrd.hxx:43
editeng::SortedAutoCompleteStrings::size_type m_nMaxCount
Definition: acmplwrd.hxx:46
SvxAutoCorrect * GetAutoCorrect()
std::vector< SwAutoCompleteClient > m_aClientVector
Definition: acmplwrd.cxx:64
virtual ~SwAutoCompleteString() override
Definition: acmplwrd.cxx:172
SwAutoCompleteClient & operator=(const SwAutoCompleteClient &rClient)
Definition: acmplwrd.cxx:126
SwAutoCompleteWord_Impl(SwAutoCompleteWord &rParent)
Definition: acmplwrd.cxx:67
const SwDoc & GetDoc() const
Definition: acmplwrd.cxx:53
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_REMOVE_UNO_OBJECT(179)
std::vector< const SwDoc * > m_aSourceDocs
Definition: acmplwrd.cxx:79
static sal_uLong s_nSwAutoCompleteStringCount
Definition: acmplwrd.cxx:77
void SetMinWordLen(sal_uInt16 n)
Definition: acmplwrd.cxx:306
sal_uInt16 m_nMinWordLen
Definition: acmplwrd.hxx:47
static sal_uLong GetElementCount()
Definition: acmplwrd.cxx:55
void RemoveDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:155
bool RemoveDocument(const SwDoc &rDoc)
Definition: acmplwrd.cxx:189
INetProtocol GetProtocol() const
const SwModify * GetRegisteredIn() const
Definition: calbck.hxx:157
void copy(const fs::path &src, const fs::path &dest)
const INetURLObject & GetURLObject() const
void SetMaxCount(editeng::SortedAutoCompleteStrings::size_type n)
Definition: acmplwrd.cxx:285
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
Standard page.
Definition: poolfmt.hxx:171
editeng::Trie m_LookupTree
Definition: acmplwrd.hxx:42
sal_uInt16 Which() const
void AddDocument(SwDoc &rDoc)
Definition: acmplwrd.cxx:147
constexpr TypedWhichId< SwPtrMsgPoolItem > RES_OBJECTDYING(RES_MSG_BEGIN)
sal_uInt16 nPos
typedef void(CALLTYPE *GetFuncDataPtr)(sal_uInt16 &nNo
SfxMedium * GetMedium() const