Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/sw/source/core/doc/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 13 kB image not shown  

Quelle  acmplwrd.cxx   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <tools/urlobj.hxx>
#include <hintids.hxx>
#include <acmplwrd.hxx>
#include <doc.hxx>
#include <pagedesc.hxx>
#include <poolfmt.hxx>
#include <svl/listener.hxx>
#include <IDocumentStylePoolAccess.hxx>
#include <editeng/svxacorr.hxx>
#include <osl/diagnose.h>

#include <editeng/acorrcfg.hxx>
#include <sfx2/docfile.hxx>
#include <docsh.hxx>

#include <cassert>
#include <vector>

class SwAutoCompleteClient : public SvtListener
{
    SwAutoCompleteWord* m_pAutoCompleteWord;
    SwDoc*              m_pDoc;
#if OSL_DEBUG_LEVEL > 0
    static sal_uLong s_nSwAutoCompleteClientCount;
#endif
public:
    SwAutoCompleteClient(SwAutoCompleteWord& rToTell, SwDoc& rSwDoc);
    SwAutoCompleteClient(const SwAutoCompleteClient& rClient);
    virtual ~SwAutoCompleteClient() override;

    SwAutoCompleteClient& operator=(const SwAutoCompleteClient& rClient);

    const SwDoc& GetDoc() const {return *m_pDoc;}
#if OSL_DEBUG_LEVEL > 0
    static sal_uLong GetElementCount() {return s_nSwAutoCompleteClientCount;}
#endif
protected:
    virtual void Notify(const SfxHint&) override;
private:
    void DocumentDying();
};

class SwAutoCompleteWord_Impl
{
    std::vector<SwAutoCompleteClient>
                                m_aClientVector;
    SwAutoCompleteWord&         m_rAutoCompleteWord;
public:
    explicit SwAutoCompleteWord_Impl(SwAutoCompleteWord& rParent) :
        m_rAutoCompleteWord(rParent){}
    void AddDocument(SwDoc& rDoc);
    void RemoveDocument(const SwDoc& rDoc);
};

class SwAutoCompleteString
    : public editeng::IAutoCompleteString
{
#if OSL_DEBUG_LEVEL > 0
    static sal_uLong s_nSwAutoCompleteStringCount;
#endif
    std::vector<const SwDoc*> m_aSourceDocs;
    public:
        SwAutoCompleteString(const OUString& rStr, sal_Int32 nLen);

        virtual ~SwAutoCompleteString() override;
        void        AddDocument(const SwDoc& rDoc);
        //returns true if last document reference has been removed
        bool        RemoveDocument(const SwDoc& rDoc);
#if OSL_DEBUG_LEVEL > 0
    static sal_uLong GetElementCount() {return s_nSwAutoCompleteStringCount;}
#endif
};
#if OSL_DEBUG_LEVEL > 0
    sal_uLong SwAutoCompleteClient::s_nSwAutoCompleteClientCount = 0;
    sal_uLong SwAutoCompleteString::s_nSwAutoCompleteStringCount = 0;
#endif

SwAutoCompleteClient::SwAutoCompleteClient(SwAutoCompleteWord& rToTell, SwDoc&&nbsp;rSwDoc) :
        m_pAutoCompleteWord(&rToTell),
        m_pDoc(&rSwDoc)
{
    StartListening(m_pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD)->GetNotifier());
#if OSL_DEBUG_LEVEL > 0
    ++s_nSwAutoCompleteClientCount;
#endif
}

SwAutoCompleteClient::SwAutoCompleteClient(const SwAutoCompleteClient& rClient) :
    SvtListener(),
    m_pAutoCompleteWord(rClient.m_pAutoCompleteWord),
    m_pDoc(rClient.m_pDoc)
{
    StartListening(m_pDoc->getIDocumentStylePoolAccess().GetPageDescFromPool(RES_POOLPAGE_STANDARD)->GetNotifier());
#if OSL_DEBUG_LEVEL > 0
    ++s_nSwAutoCompleteClientCount;
#endif
}

SwAutoCompleteClient::~SwAutoCompleteClient()
{
#if OSL_DEBUG_LEVEL > 0
    --s_nSwAutoCompleteClientCount;
#else
    (voidthis;
#endif
}

SwAutoCompleteClient& SwAutoCompleteClient::operator=(const SwAutoCompleteClient& rClient)
{
    m_pAutoCompleteWord = rClient.m_pAutoCompleteWord;
    m_pDoc = rClient.m_pDoc;
    CopyAllBroadcasters(rClient);
    return *this;
}

void SwAutoCompleteClient::DocumentDying()
{
    EndListeningAll();
    m_pAutoCompleteWord->DocumentDying(*m_pDoc);
}

void SwAutoCompleteClient::Notify(const SfxHint& rHint)
{
    switch(rHint.GetId())
    {
        case SfxHintId::Dying:
            DocumentDying();
            return;
        case SfxHintId::SwRemoveUnoObject:
            DocumentDying();
            return;
        case SfxHintId::SwObjectDying:
            DocumentDying();
            return;
        default:
            return;
    }
}

void SwAutoCompleteWord_Impl::AddDocument(SwDoc& rDoc)
{
    if (std::any_of(m_aClientVector.begin(), m_aClientVector.end(),
            [&rDoc](SwAutoCompleteClient& rClient) { return &rClient.GetDoc() == &rDoc; }))
        return;
    m_aClientVector.emplace_back(m_rAutoCompleteWord, rDoc);
}

void SwAutoCompleteWord_Impl::RemoveDocument(const SwDoc& rDoc)
{
    auto aIt = std::find_if(m_aClientVector.begin(), m_aClientVector.end(),
        [&rDoc](SwAutoCompleteClient& rClient) { return &rClient.GetDoc() == &rDoc; });
    if (aIt != m_aClientVector.end())
        m_aClientVector.erase(aIt);
}

SwAutoCompleteString::SwAutoCompleteString(
            const OUString& rStr, sal_Int32 const nLen)
    : editeng::IAutoCompleteString(rStr.copy(0, nLen))
{
#if OSL_DEBUG_LEVEL > 0
    ++s_nSwAutoCompleteStringCount;
#endif
}

SwAutoCompleteString::~SwAutoCompleteString()
{
#if OSL_DEBUG_LEVEL > 0
    --s_nSwAutoCompleteStringCount;
#else
    (voidthis;
#endif
}

void SwAutoCompleteString::AddDocument(const SwDoc& rDoc)
{
    auto aIt = std::find(m_aSourceDocs.begin(), m_aSourceDocs.end(), &rDoc);
    if (aIt != m_aSourceDocs.end())
        return;
    m_aSourceDocs.push_back(&rDoc);
}

bool SwAutoCompleteString::RemoveDocument(const SwDoc& rDoc)
{
    auto aIt = std::find(m_aSourceDocs.begin(), m_aSourceDocs.end(), &rDoc);
    if (aIt != m_aSourceDocs.end())
    {
        m_aSourceDocs.erase(aIt);
        return m_aSourceDocs.empty();
    }
    return false;
}

SwAutoCompleteWord::SwAutoCompleteWord(
    editeng::SortedAutoCompleteStrings::size_type nWords, sal_uInt16 nMWrdLen ):
    m_pImpl(new SwAutoCompleteWord_Impl(*this)),
    m_nMaxCount( nWords ),
    m_nMinWordLen( nMWrdLen ),
    m_bLockWordList( false )
{
}

SwAutoCompleteWord::~SwAutoCompleteWord()
{
    m_WordList.DeleteAndDestroyAll(); // so the assertion below works
#if OSL_DEBUG_LEVEL > 0
    sal_uLong nStrings = SwAutoCompleteString::GetElementCount();
    sal_uLong nClients = SwAutoCompleteClient::GetElementCount();
    OSL_ENSURE(!nStrings && !nClients, "AutoComplete: clients or string count mismatch");
#endif
}

bool SwAutoCompleteWord::InsertWord( const OUString& rWord, SwDoc& rDoc )
{
    SwDocShell* pDocShell = rDoc.GetDocShell();
    SfxMedium* pMedium = pDocShell ? pDocShell->GetMedium() : nullptr;
    // strings from help module should not be added
    if( pMedium )
    {
        const INetURLObject& rURL = pMedium->GetURLObject();
        if ( rURL.GetProtocol() == INetProtocol::VndSunStarHelp )
            return false;
    }

    OUString aNewWord = rWord.replaceAll(OUStringChar(CH_TXTATR_INWORD), "")
                             .replaceAll(OUStringChar(CH_TXTATR_BREAKWORD), "");

    m_pImpl->AddDocument(rDoc);
    bool bRet = false;
    sal_Int32 nWrdLen = aNewWord.getLength();
    while( nWrdLen && '.' == aNewWord[ nWrdLen-1 ])
        --nWrdLen;

    if( !m_bLockWordList && nWrdLen >= m_nMinWordLen )
    {
        SwAutoCompleteString* pNew = new SwAutoCompleteString( aNewWord, nWrdLen );
        pNew->AddDocument(rDoc);
        std::pair<editeng::SortedAutoCompleteStrings::const_iterator, bool>
            aInsPair = m_WordList.insert(pNew);

        m_LookupTree.insert( aNewWord.subView(0, nWrdLen) );

        if (aInsPair.second)
        {
            bRet = true;
            if (m_aLRUList.size() >= m_nMaxCount)
            {
                // the last one needs to be removed
                // so that there is space for the first one
                SwAutoCompleteString* pDel = m_aLRUList.back();
                m_aLRUList.pop_back();
                m_WordList.erase(pDel);
                delete pDel;
            }
            m_aLRUList.push_front(pNew);
        }
        else
        {
            delete pNew;
            // then move "up"
            pNew = static_cast<SwAutoCompleteString*>(*aInsPair.first);

            // add the document to the already inserted string
            pNew->AddDocument(rDoc);

            // move pNew to the front of the LRU list
            SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pNew );
            OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
            if ( m_aLRUList.begin() != it && m_aLRUList.end() != it )
            {
                m_aLRUList.erase( it );
                m_aLRUList.push_front( pNew );
            }
        }
    }
    return bRet;
}

void SwAutoCompleteWord::SetMaxCount(
    editeng::SortedAutoCompleteStrings::size_type nNewMax )
{
    if( nNewMax < m_nMaxCount && m_aLRUList.size() > nNewMax )
    {
        // remove the trailing ones
        SwAutoCompleteStringPtrDeque::size_type nLRUIndex = nNewMax-1;
        while (nNewMax < m_WordList.size() && nLRUIndex < m_aLRUList.size())
        {
            auto it = m_WordList.find(m_aLRUList[nLRUIndex++]);
            OSL_ENSURE( m_WordList.end() != it, "String not found" );
            editeng::IAutoCompleteString *const pDel = *it;
            m_WordList.erase(it);
            delete pDel;
        }
        m_aLRUList.erase( m_aLRUList.begin() + nNewMax - 1, m_aLRUList.end() );
    }
    m_nMaxCount = nNewMax;
}

void SwAutoCompleteWord::SetMinWordLen( sal_uInt16 n )
{
    // Do you really want to remove all words that are less than the minWrdLen?
    if( n < m_nMinWordLen )
    {
        size_t nPos = 0;
        while (nPos < m_WordList.size())
        {
            if (m_WordList[ nPos ]->GetAutoCompleteString().getLength() < n)
            {
                SwAutoCompleteString *const pDel =
                    dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos]);
                m_WordList.erase_at(nPos);

                SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
                OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
                m_aLRUList.erase( it );
                delete pDel;
                continue;
            }
            ++nPos;
        }
    }

    m_nMinWordLen = n;
}

/** Return all words matching a given prefix
 *
 *  @param aMatch the prefix to search for
 *  @param rWords the words found matching
 */

bool SwAutoCompleteWord::GetWordsMatching(std::u16string_view aMatch, std::vector<OUString>& rWords) const
{
    assert(rWords.empty());
    m_LookupTree.findSuggestions(aMatch, rWords);
    return !rWords.empty();
}

void SwAutoCompleteWord::CheckChangedList(
        const editeng::SortedAutoCompleteStrings& rNewLst)
{
    size_t nMyLen = m_WordList.size(), nNewLen = rNewLst.size();
    size_t nMyPos = 0, nNewPos = 0;

    for( ; nMyPos < nMyLen && nNewPos < nNewLen; ++nMyPos, ++nNewPos )
    {
        const editeng::IAutoCompleteString * pStr = rNewLst[ nNewPos ];
        while (m_WordList[nMyPos] != pStr)
        {
            SwAutoCompleteString *const pDel =
                dynamic_cast<SwAutoCompleteString*>(m_WordList[nMyPos]);
            m_WordList.erase_at(nMyPos);
            SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
            OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
            m_aLRUList.erase( it );
            delete pDel;
            if( nMyPos >= --nMyLen )
                break;
        }
    }
    // remove the elements at the end of the array
    if( nMyPos >= nMyLen )
        return;

    // clear LRU array first then delete the string object
    for( ; nNewPos < nMyLen; ++nNewPos )
    {
        SwAutoCompleteString *const pDel =
            dynamic_cast<SwAutoCompleteString*>(m_WordList[nNewPos]);
        SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pDel );
        OSL_ENSURE( m_aLRUList.end() != it, "String not found" );
        m_aLRUList.erase( it );
        delete pDel;
    }
    // remove from array
    m_WordList.erase(m_WordList.begin() + nMyPos,
                     m_WordList.begin() + nMyLen);
}

void SwAutoCompleteWord::DocumentDying(const SwDoc& rDoc)
{
    m_pImpl->RemoveDocument(rDoc);

    SvxAutoCorrect* pACorr = SvxAutoCorrCfg::Get().GetAutoCorrect();
    const bool bDelete = !pACorr->GetSwFlags().bAutoCmpltKeepList;
    for (size_t nPos = m_WordList.size(); nPos; nPos--)
    {
        SwAutoCompleteString *const pCurrent = dynamic_cast<SwAutoCompleteString*>(m_WordList[nPos - 1]);
        if(pCurrent && pCurrent->RemoveDocument(rDoc) && bDelete)
        {
            m_WordList.erase_at(nPos - 1);
            SwAutoCompleteStringPtrDeque::iterator it = std::find( m_aLRUList.begin(), m_aLRUList.end(), pCurrent );
            OSL_ENSURE( m_aLRUList.end() != it, "word not found in LRU list" );
            m_aLRUList.erase( it );
            delete pCurrent;
        }
    }
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Messung V0.5
C=94 H=92 G=92

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.