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

Generated by: LCOV version 1.10