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