LCOV - code coverage report
Current view: top level - sw/source/core/doc - acmplwrd.cxx (source / functions) Hit Total Coverage
Test: commit e02a6cb2c3e2b23b203b422e4e0680877f232636 Lines: 0 167 0.0 %
Date: 2014-04-14 Functions: 0 24 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10