//+---------------------------------------------------------------------------
//
//  Microsoft Windows
//  Copyright (C) Microsoft Corporation, 1991 - 2000.
//
//  File:   QKREP.CXX
//
//  Contents:   Query Key Repository
//
//  Classes:    CQueryKeyRepository
//
//  History:    04-Jun-91    t-WadeR    Created.
//              23-Sep-91    BartosM    Rewrote to use phrase expr.
//              31-Jan-93    KyleP      Use restrictions, not expressions
//
//----------------------------------------------------------------------------

#include <pch.cxx>
#pragma hdrstop

#include <qparse.hxx>
#include <irest.hxx>

#include "qkrep.hxx"

#include <drep.hxx>

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::CQueryKeyRepository
//
//  Synopsis:   Creates Key repository
//
//  History:    31-May-91   t-WadeR     Created
//              23-Sep-91   BartoszM    Rewrote to use phrase expr.
//
//----------------------------------------------------------------------------

CQueryKeyRepository::CQueryKeyRepository ( ULONG fuzzy )
        : _occLast(OCC_INVALID),
          _pOrRst(0),
          _pCurAltPhrase(0),
          _cInitialNoiseWords(0),
          _fNoiseWordsOnly(FALSE),
          _fHasSynonym( FALSE )
{
    if ( fuzzy == GENERATE_METHOD_PREFIX )
        _isRange = TRUE;
    else
        _isRange = FALSE;

    _pPhrase = new CPhraseRestriction( INIT_PHRASE_WORDS );
    Win4Assert( _pPhrase->IsValid() );
}

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::~CQueryKeyRepository
//
//  Synopsis:   Destroys
//
//  History:    31-May-91   t-WadeR     Created
//              23-Sep-91   BartoszM    Rewrote to use phrase expr.
//
//----------------------------------------------------------------------------

CQueryKeyRepository::~CQueryKeyRepository()
{
    delete _pPhrase;
    delete _pOrRst;
    delete _pCurAltPhrase;
}

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::AcqXpr
//
//  Synopsis:   Acquire Phrase(s)
//
//  History:    07-Feb-92   BartoszM    Created
//              24-Jan-97   KyleP       Handle null phrase (from bad alt words)
//
//----------------------------------------------------------------------------

CRestriction * CQueryKeyRepository::AcqRst()
{
    CNodeRestriction *pNodeRst;

    if ( _pOrRst )
    {
        Win4Assert( _pPhrase == 0 );
        pNodeRst = _pOrRst;
    }
    else
        pNodeRst = _pPhrase;

    //
    // pNodeRst may be null, if alternate phrasing didn't work out.
    //

    if ( 0 == pNodeRst )
        return 0;

    switch( pNodeRst->Count() )
    {
    case 0:
        return( 0 );
        break;

    case 1:
        return( pNodeRst->RemoveChild(0) );
        break;

    default:
    {
        CRestriction * tmp = pNodeRst;
        _pOrRst = 0;
        _pPhrase = 0;
        return( tmp );
        break;
    }
    }
} //AcqRst

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::PutKey
//
//  Synopsis:   Puts a key into the key list and occurrence list
//
//  Arguments:  [cNoiseWordsSkipped] -- count of noise words that have been skipped
//
//  History:    31-May-91   t-WadeR     Created
//              23-Sep-91   BartoszM    Rewrote to use phrase expr.
//              29-Nov-94   SitaramR    Rewrote to take Start/EndAltPhrase into account
//
//----------------------------------------------------------------------------

void CQueryKeyRepository::PutKey ( ULONG cNoiseWordsSkipped )
{
    // check if there is a set of alt phrases with noise words only
    if ( _fNoiseWordsOnly )
        return;

    ciDebugOut (( DEB_ITRACE, "QueryKeyRepository::PutKey \"%.*ws\", pid = %d\n",
                  _key.StrLen(), _key.GetStr(), _key.Pid() ));

    if ( _pCurAltPhrase )   // if, we are processing an alternate phrase
        AppendKey( _pCurAltPhrase, cNoiseWordsSkipped );
    else
    {
        if ( _pOrRst )
        {
            Win4Assert( _pOrRst->Count() );
            Win4Assert( _pPhrase == 0 );

            for ( unsigned i=0; i<_pOrRst->Count(); i++)
            {
                CRestriction *pRst = _pOrRst->GetChild(i);
                Win4Assert( pRst->Type() == RTPhrase );
                AppendKey( (CPhraseRestriction *) pRst, cNoiseWordsSkipped );
            }
        }
        else
            AppendKey( _pPhrase, cNoiseWordsSkipped );
    }

    _occLast = _occ;
} //PutKey

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::AppendKey
//
//  Synopsis:   Appends a key to end of phraseRst
//
//  Arguments:  [pPhraseRst]         -- restriction to append to
//              [cNoiseWordsSkipped] -- count of noise words that have been skipped
//
//  History:    29-Nov-94   SitaramR    Created
//
//----------------------------------------------------------------------------

void CQueryKeyRepository::AppendKey( CPhraseRestriction *pPhraseRst,
                                     ULONG cNoiseWordsSkipped )
{
    // _occ as generated by CKeyMaker is not accurate because it does not
    //  take StartAltPhrase/EndAltPhrase into account. We use _occ (and _occLast)
    //  solely to test for synonyms. The test is:
    //
    //       if ( _occ == _occLast )
    //          then synonym

    if ( _occ == _occLast )
    {
        ULONG iLast = pPhraseRst->Count()-1;
        COccRestriction *pLastChild = pPhraseRst->GetChild( iLast );

        Win4Assert( pLastChild );

        if ( pLastChild->Type() == RTWord )
        {
            ciDebugOut (( DEB_ITRACE, "Create Synonym Expression\n" ));
            const CKey* pKey = ((CWordRestriction*) pLastChild)->GetKey();

            // there can be no noise words between synonyms
            Win4Assert( cNoiseWordsSkipped == 0 );

            _fHasSynonym = TRUE;
            XPtr<CSynRestriction> xTmp(new CSynRestriction ( *pKey,
                                                         pLastChild->Occurrence(),
                                                         0, 0, _isRange ));
            Win4Assert( xTmp->IsValid() );

            delete pLastChild;
            pLastChild = xTmp.Acquire();
            pPhraseRst->SetChild ( pLastChild, iLast );
        }

        Win4Assert ( pLastChild->Type() == RTSynonym );

        ((CSynRestriction*) pLastChild)->AddKey ( _key );
    }
    else
    {
        XPtr<CWordRestriction> xChildRst( new CWordRestriction( _key, _occ,
                                                                cNoiseWordsSkipped, 0, _isRange ) );
        Win4Assert( xChildRst->IsValid() );

        // calculate correct occurrence taking noise words into account

        OCCURRENCE occ = _ComputeOccurrence( xChildRst.GetPointer(), pPhraseRst );
        xChildRst->SetOccurrence( occ );

        pPhraseRst->AddChild ( xChildRst.GetPointer() );
        xChildRst.Acquire();
    }
} //AppendKey

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::StartAltPhrase
//
//  Synopsis:   Preparation for start of an alternate phrase
//
//  Arguments:  [cNoiseWordsSkipped] -- count of noise words that have been skipped
//
//  History:    29-Nov-94   SitaramR    Created
//
//----------------------------------------------------------------------------

void CQueryKeyRepository::StartAltPhrase( ULONG cNoiseWordsSkipped )
{
    // check if there is a set of alt phrases with noise words only
    if ( _fNoiseWordsOnly )
        return;

    if ( _pCurAltPhrase )
    {
        if ( _pCurAltPhrase->Count() == 0 )
            delete _pCurAltPhrase;
        else
        {
            // add count of noise words skipped to last child of _pCurAltPhrase
            COccRestriction *pOccRst = _pCurAltPhrase->GetChild( _pCurAltPhrase->Count()-1 );
            Win4Assert( pOccRst );
            pOccRst->AddCountPostNoiseWords( cNoiseWordsSkipped );
            _stkAltPhrases.Push( _pCurAltPhrase );
        }
    }
    else
    {
        if ( _pOrRst )
        {
            Win4Assert( _pOrRst->Count() );
            Win4Assert( _pPhrase == 0 );

            // add count of noise words of last child of every phrase in _pOrRst
            for ( unsigned i=0; i<_pOrRst->Count(); i++)
            {
                CRestriction *pRst = _pOrRst->GetChild(i);
                Win4Assert( pRst->Type() == RTPhrase );
                COccRestriction *pOccRst =
                      ((CPhraseRestriction *)pRst)->GetChild( ((CPhraseRestriction *)pRst)->Count()-1 );
                Win4Assert( pOccRst );
                pOccRst->AddCountPostNoiseWords( cNoiseWordsSkipped );
            }
        }
        else
        {
            if ( _pPhrase->Count() != 0 )
            {
                // add count of noise words skipped to last child of _pPhrase
                COccRestriction *pOccRst = _pPhrase->GetChild( _pPhrase->Count()-1 );
                Win4Assert( pOccRst );
                pOccRst->AddCountPostNoiseWords( cNoiseWordsSkipped );
            }
            else  // sequence of noise words at the beginning of the phrase
                _cInitialNoiseWords = cNoiseWordsSkipped;
        }
    }

    _pCurAltPhrase = new CPhraseRestriction( INIT_PHRASE_WORDS );

    _occLast = OCC_INVALID;             // reset _occLast
}





//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::EndAltPhrase
//
//  Synopsis:   Append all alternate phrases to existing phrases
//
//  Arguments:  [cNoiseWordsSkipped] -- count of noise words that have been skipped
//
//  History:    29-Nov-94   SitaramR    Created
//
//----------------------------------------------------------------------------

void CQueryKeyRepository::EndAltPhrase( ULONG cNoiseWordsSkipped )
{
    // check if there is a set of alt phrases with noise words only
    if ( _fNoiseWordsOnly )
        return;

    // call on StartAltPhrase to stack the current alternate phrase
    Win4Assert( _pCurAltPhrase );
    StartAltPhrase( cNoiseWordsSkipped );
    delete _pCurAltPhrase;         // allocated in StartAltPhrase, but it is not needed
    _pCurAltPhrase = 0;

    // if all alternate phrases are noise, then the entire query is an
    //      uninteresting phrase because we cannot compute the occurrence of the
    //      first key after the set of alternate phrases. So, clean up and return.
    if ( _stkAltPhrases.Count() == 0 )
    {
        _fNoiseWordsOnly = TRUE;

        delete _pOrRst;
        _pOrRst = 0;
        delete _pPhrase;
        _pPhrase = 0;

        return;
    }

    XNodeRestriction xNewOrRst( new CNodeRestriction( RTOr ));

    XPhraseRestriction xTailPhrase;

    if ( _pOrRst )
    {
        // concatenate each of the stacked alternate phrases to every child phrase
        //    of _pOrRst

        Win4Assert( _pOrRst->Count() );
        Win4Assert( _pPhrase == 0 );

        while ( _stkAltPhrases.Count() > 0 )
        {
            xTailPhrase.Set( _stkAltPhrases.Pop() );
            for ( unsigned i=0; i< _pOrRst->Count(); i++)
            {
                CRestriction *pRst = _pOrRst->GetChild(i);
                Win4Assert( pRst->Type() == RTPhrase );
                CloneAndAdd( xNewOrRst.GetPointer(), (CPhraseRestriction *)pRst,
                             xTailPhrase.GetPointer() );
            }
            CPhraseRestriction *pTailPhrase = xTailPhrase.Acquire();
            delete pTailPhrase;
        }
    }
    else       // only one phrase so far
    {
        while ( _stkAltPhrases.Count() > 0 )
        {
            xTailPhrase.Set( _stkAltPhrases.Pop() );
            CloneAndAdd( xNewOrRst.GetPointer(), _pPhrase, xTailPhrase.GetPointer() );
            CPhraseRestriction *pTailPhrase = xTailPhrase.Acquire();
            delete pTailPhrase;
        }
    }

    delete _pPhrase;
    _pPhrase = 0;

    delete _pOrRst;
    _pOrRst  = xNewOrRst.Acquire();

    _occLast = OCC_INVALID;             // reset _occLast
}



//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::CloneAndAdd
//
//  Synopsis:   Clone pHeadPhrase,  pTailPhrase, concatenate and add the
//                 resulting phrase to pOrRst
//
//  Arguments:  [pOrRst] -- Destination Or node
//              [pHeadPhrase] -- first part of a phrase
//              [pTailPhrase] -- remaining part of a phrase
//
//  History:    29-Nov-94   SitaramR    Created
//
//----------------------------------------------------------------------------

void CQueryKeyRepository::CloneAndAdd( CNodeRestriction *pOrRst,
                                       CPhraseRestriction *pHeadPhrase,
                                       CPhraseRestriction *pTailPhrase )
{
    XPhraseRestriction xPhraseRst( new CPhraseRestriction( INIT_PHRASE_WORDS ) );

    Win4Assert( xPhraseRst->IsValid() );

    // clone head
    XOccRestriction xOccRst;
    for ( unsigned i=0; i<pHeadPhrase->Count(); i++ )
    {
        xOccRst.Set( pHeadPhrase->GetChild(i)->Clone() );

        Win4Assert( xOccRst->IsValid() );

        xPhraseRst.GetPointer()->AddChild( xOccRst.GetPointer() );
        xOccRst.Acquire();
    }

    // clone tail
    for ( i=0; i<pTailPhrase->Count(); i++)
    {
        xOccRst.Set( pTailPhrase->GetChild(i)->Clone() );

        Win4Assert( xOccRst->IsValid() );

        OCCURRENCE occ = _ComputeOccurrence( xOccRst.GetPointer(), xPhraseRst.GetPointer() );
        xOccRst.GetPointer()->SetOccurrence( occ );

        xPhraseRst.GetPointer()->AddChild( xOccRst.GetPointer() );
        xOccRst.Acquire();
    }

    pOrRst->AddChild( xPhraseRst.GetPointer() );
    xPhraseRst.Acquire();
}


//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::_ComputeOccurrence
//
//  Synopsis:   Computes the noise word adjusted occurrence
//
//  Arguments:  [pOccRst] -- restriction whose occurrence is to be computed
//              [pPhrase] -- phrase to which pOccRst is being appended
//
//  History:    29-Nov-94   SitaramR    Created
//
//----------------------------------------------------------------------------

OCCURRENCE CQueryKeyRepository::_ComputeOccurrence( COccRestriction *pOccRst,
                                                    CPhraseRestriction *pPhraseRst )
{
    OCCURRENCE occ;
    if ( pPhraseRst->Count() )
    {
        COccRestriction *pPrevOccRst = pPhraseRst->GetChild( pPhraseRst->Count()-1 );
        Win4Assert( pPrevOccRst );

        // Occurrence of pOccRst is computed as:
        //    occurrence of previous child (pPrevOccRst) in pPhraseRst
        //  + count of noise words following pPrevOccRst
        //  + count of noise words preceeding pOccRst
        //  + 1
        occ = pPrevOccRst->Occurrence() + pPrevOccRst->CountPostNoiseWords() +
                       pOccRst->CountPrevNoiseWords() + 1;
    }
    else
    {
        // Since there are no preivous restrictions, occurrence of
        //    pOccRst is computed as:
        //
        //    count of noise words at the beginning of phrase
        //  + count of noise words preceeding pOccRst
        //  + 1
        occ = _cInitialNoiseWords + pOccRst->CountPrevNoiseWords() + 1;
    }
    return occ;
}



//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::GetBuffers
//
//  Synopsis:   Returns address of repository's input buffers
//
//  Effects:
//
//  Arguments:  [ppcbInBuf] -- pointer to pointer to size of input buffer
//              [ppbInBuf] -- pointer to pointer to recieve address of buffer
//              [ppocc] -- pointer to pointer to recieve address of occurrences
//
//  History:    05-June-91  t-WadeR     Created.
//
//  Notes:
//
//----------------------------------------------------------------------------

void CQueryKeyRepository::GetBuffers( unsigned** ppcbWordBuf,
                                      BYTE** ppbWordBuf, OCCURRENCE** ppocc )
{
    _key.SetCount(MAXKEYSIZE);
    *ppcbWordBuf = _key.GetCountAddress();
    *ppbWordBuf = _key.GetWritableBuf();
    *ppocc = &_occ;
}

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::GetFlags
//
//  Synopsis:   Returns address of rank and range flags
//
//  Arguments:  [ppRange] -- range flag
//              [ppRank] -- rank flag
//
//  History:    11-Feb-92   BartoszM    Created.
//
//----------------------------------------------------------------------------

void  CQueryKeyRepository::GetFlags ( BOOL** ppRange, CI_RANK** ppRank )
{
    *ppRange = &_isRange;
    *ppRank  = &_rank;
}

//+---------------------------------------------------------------------------
//
//  Member:     CQueryKeyRepository::FixUp
//
//  Synopsis:   This funstion creates a word restriction with the cached phrase
//              in the CDataRepository. Then it connects the new Word Restriction
//              to the phrase (internal restriction ) with a new Or restriction.
//              If the internal restriction is an Or restriction, than it simply
//              do a AddChild to the Or restriction.
//
//  Arguments : [drep] -- CDataRepository containing the cached phrase
//
//  History:    10-Feb-2000   KitmanH   Created
//
//  Note:       This function is a hack to fix a word breaker issue. The word
//              breaker does compund word breaking for some languages, such as
//              German. For example, "tes" is broken into "tes" and "1".
//              "tes" get a synonyn "t" and "1" gets a synonym "es". This is a
//              result of a hack in the infosoft word breaker. The "1" is a place
//              holder and is thrown out in a non prefix match phrase to capture
//              the case ("tes" | "t") "es". However, this breaks the prefix
//              matching scenerio. Noise words are not thrown out in a prefix
//              matching (GENERATE_METHOD_PREFIX) query, "tes*" becomes
//              (tes*|t*) (1*|es*). In this case, tes*" is not a match unless
//              it is followed immediately with a 1* or es*, e.g. "test case"
//              is not a match whereas "tested 1000 times" and "testing especially"
//              are matches. The hack here is to Or a CWordRestriction of the
//              originally phrase without word breaking. This hack works fine,
//              if the original phrase is a single word. It will not work in the
//              multiple word case.
//
//----------------------------------------------------------------------------

void CQueryKeyRepository::FixUp( CDataRepository & drep )
{
    //
    // If the keyRep has synonym, we assume word breaking has occured.
    //

    if ( _isRange && _fHasSynonym )
    {
        XNodeRestriction xOrRst;

        if ( _pPhrase )
        {
            xOrRst.Set( new CNodeRestriction( RTOr, 2 ) );
            xOrRst->AddChild ( _pPhrase );
        }
        else
        {
            Win4Assert( 0 != _pOrRst );
            xOrRst.Set( _pOrRst );
        }

        CKeyBuf KeyBuf;
        KeyBuf.SetPid( _key.Pid() );

        drep.NormalizeWStr( KeyBuf.GetWritableBuf(), KeyBuf.GetCountAddress() );

        // Create a CWordRestriction with the Normalized form of the whole phrase
        XPtr<CWordRestriction> xWordRst( new CWordRestriction( KeyBuf,
                                                               0, // occurence
                                                               0,
                                                               0,
                                                               TRUE ) );
        xOrRst->AddChild( xWordRst.GetPointer() );
        xWordRst.Acquire();

        _pOrRst = xOrRst.Acquire();
        _pPhrase = 0;
    }
}

//+---------------------------------------------------------------------------
//
//  Member:     CVectorKeyRepository::CVectorKeyRepository
//
//  Synopsis:   Creates Vector Key repository
//
//  History:    18-Jan-95   SitaramR    Created
//
//----------------------------------------------------------------------------

CVectorKeyRepository::CVectorKeyRepository( const CFullPropSpec & ps,
                                            LCID lcid,
                                            ULONG ulWeight,
                                            CPidMapper & pidMap,
                                            CLangList  & langList )
        : _occLast(OCC_INVALID),
          _ps(ps),
          _lcid(lcid),
          _ulWeight(ulWeight),
          _pidMap(pidMap),
          _langList( langList )
{
    _pVectorRst = new CVectorRestriction( VECTOR_RANK_JACCARD );
}

//+---------------------------------------------------------------------------
//
//  Member:     CVectorKeyRepository::~CVectorKeyRepository
//
//  History:    18-Jan-95   SitaramR    Created
//
//----------------------------------------------------------------------------

CVectorKeyRepository::~CVectorKeyRepository()
{
    delete _pVectorRst;
}

//+---------------------------------------------------------------------------
//
//  Member:     CVectorKeyRepository::AcqRst
//
//  Synopsis:   Acquire vector restriction
//
//  History:    18-Jan-95   SitaramR    Created
//
//----------------------------------------------------------------------------

CVectorRestriction* CVectorKeyRepository::AcqRst()
{
    if ( _pVectorRst->Count() == 0 )
        return 0;
    else
    {
        CVectorRestriction *pTmp = _pVectorRst;
        _pVectorRst = 0;
        return pTmp;
    }
}



//+---------------------------------------------------------------------------
//
//  Member:     CVectorKeyRepository::PutKey
//
//  Synopsis:   Adds a key to the vector restriction
//
//  Arguments:  cNoiseWordsSkipped -- ignored (used by CQueryKeyRepository::PutKey )
//
//  History:    18-Jan-95   SitaramR    Created
//
//----------------------------------------------------------------------------

void CVectorKeyRepository::PutKey( ULONG cNoiseWordsSkipped )
{
    ciDebugOut (( DEB_ITRACE, "VectorKeyRepository::PutKey \"%.*ws\", pid=%d\n",
                  _key.StrLen(), _key.GetStr(), _key.Pid() ));

    // _occ as generated by CKeyMaker is not accurate because it does not
    //  take StartAltPhrase/EndAltPhrase into account. We use _occ (and _occLast)
    //  solely to test for synonyms. The test is:
    //
    //       if ( _occ == _occLast )
    //          then synonym

    if ( _occ == _occLast )
    {
        ULONG iLast = _pVectorRst->Count()-1;
        COccRestriction *pLastChild = (COccRestriction *)_pVectorRst->GetChild( iLast );

        Win4Assert( pLastChild );

        if ( pLastChild->Type() == RTWord )
        {
            ciDebugOut (( DEB_ITRACE, "Create Synonym Expression\n" ));
            const CKey* pKey = ((CWordRestriction*) pLastChild)->GetKey();

            // there can be no noise words between synonyms
            Win4Assert( cNoiseWordsSkipped == 0 );

            CSynRestriction* tmp = new CSynRestriction ( *pKey,
                                                         pLastChild->Occurrence(),
                                                         0, 0, FALSE );
            Win4Assert( tmp->IsValid() );

            delete pLastChild;
            pLastChild = tmp;
            _pVectorRst->SetChild ( tmp, iLast );
        }

        Win4Assert ( pLastChild->Type() == RTSynonym );

        ((CSynRestriction*) pLastChild)->AddKey ( _key );
    }
    else
    {
        XWordRestriction xWordRst( new CWordRestriction( _key, 1, 0, 0, FALSE ));

        _pVectorRst->AddChild( xWordRst.GetPointer() );
        xWordRst.Acquire();
    }

    _occLast = _occ;
}



//+---------------------------------------------------------------------------
//
//  Member:     CVectorKeyRepository::GetBuffers
//
//  Synopsis:   Returns address of repository's input buffers
//
//  Arguments:  [ppcbInBuf] -- pointer to pointer to size of input buffer
//              [ppbInBuf] -- pointer to pointer to recieve address of buffer
//              [ppocc] -- pointer to pointer to recieve address of occurrences
//
//  History:    18-Jan-95    SitaramR     Created.
//
//----------------------------------------------------------------------------

void CVectorKeyRepository::GetBuffers( unsigned** ppcbWordBuf,
                                       BYTE** ppbWordBuf, OCCURRENCE** ppocc )
{
    _key.SetCount(MAXKEYSIZE);
    *ppcbWordBuf = _key.GetCountAddress();
    *ppbWordBuf = _key.GetWritableBuf();
    *ppocc = &_occ;
}

//+---------------------------------------------------------------------------
//
//  Member:     CVectorKeyRepository::GetFlags
//
//  Synopsis:   Returns address of rank and range flags
//
//  Arguments:  [ppRange] -- range flag
//              [ppRank] -- rank flag
//
//  History:    18-Jan-95    SitaramR    Created.
//
//----------------------------------------------------------------------------

void  CVectorKeyRepository::GetFlags ( BOOL** ppRange, CI_RANK** ppRank )
{
    *ppRange = 0;
    *ppRank  = 0;
}

//+---------------------------------------------------------------------------
//
//  Member:     CVectorKeyRepository::PutPhrase
//
//  Synopsis:   Stores query time phrases
//
//  Arguments:  [pwcPhrase] -- phrase as it exists in the text sources
//              [cwcPhrase] -- count of characters in pwcPhrase
//
//  History:    14-Feb-95    SitaramR    Created.
//
//----------------------------------------------------------------------------

SCODE CVectorKeyRepository::PutPhrase( WCHAR const *pwcPhrase, ULONG cwcPhrase )
{
    XPtrST<WCHAR> xString( new WCHAR[cwcPhrase+1] );
    RtlCopyMemory( xString.GetPointer(), pwcPhrase, cwcPhrase*sizeof(WCHAR) );
    xString.GetPointer()[cwcPhrase] = 0;

    CQueryKeyRepository keyRep( GENERATE_METHOD_EXACT );

    BreakPhrase( xString.GetPointer(), _ps, _lcid, GENERATE_METHOD_EXACT, keyRep, 0, _pidMap, _langList );

    CRestriction *pPhraseRst = keyRep.AcqRst();
    if ( 0 != pPhraseRst )
    {
        XPtr<CRestriction> xRst( pPhraseRst );
        pPhraseRst->SetWeight( _ulWeight );
        _pVectorRst->AddChild( pPhraseRst );
        xRst.Acquire();
    }

    _occLast = OCC_INVALID;             // reset _occLast

    return S_OK;
}


//
// The following are needed to make midl happy.  There are no other interfaces
// to bind to.  Inheritance from IUnknown is unnecessary.
//

SCODE STDMETHODCALLTYPE CVectorKeyRepository::QueryInterface(REFIID riid, void  * * ppvObject)
{
    *ppvObject = 0;
    return( E_NOTIMPL );
}

ULONG STDMETHODCALLTYPE CVectorKeyRepository::AddRef()
{
    return( 1 );
}

ULONG STDMETHODCALLTYPE CVectorKeyRepository::Release()
{
    return( 1 );
}