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