ANCHOR.CXX

//+--------------------------------------------------------------------------- 
//
// Copyright 1992 - 1998 Microsoft Corporation.
//
// File: anchor.cxx
//
// Contents: Parsing algorithm for anchor tag in Html
//
// Classes: CAnchorTag
//
//----------------------------------------------------------------------------

#include <pch.cxx>
#pragma hdrstop

#include <anchor.hxx>
#include <htmlguid.hxx>

//+-------------------------------------------------------------------------
//
// Method: CAnchorTag::CAnchorTag
//
// Synopsis: Constructor
//
// Arguments: [htmlIFilter] -- Html IFilter
// [serialStream] -- Input stream
//
//--------------------------------------------------------------------------

CAnchorTag::CAnchorTag( CHtmlIFilter& htmlIFilter,
CSerialStream& serialStream )
: CHtmlElement(htmlIFilter, serialStream),
_eState(StartAnchor),
_pwcHrefBuf(0),
_uLenHrefBuf(0),
_cHrefChars(0),
_cHrefCharsFiltered(0)
{
}



//+-------------------------------------------------------------------------
//
// Method: CAnchorTag::~CAnchorTag
//
// Synopsis: Destructor
//
// Arguments: [htmlIFilter] -- Html IFilter
// [serialStream] -- Input stream
//
//--------------------------------------------------------------------------

CAnchorTag::~CAnchorTag()
{
delete[] _pwcHrefBuf;
}


//+-------------------------------------------------------------------------
//
// Method: CAnchorTag::GetChunk
//
// Synopsis: Gets the next chunk and returns chunk information in pStat
//
// Arguments: [pStat] -- chunk information returned here
//
//--------------------------------------------------------------------------

SCODE CAnchorTag::GetChunk( STAT_CHUNK * pStat )
{
//
// Toggle state
//
if ( _eState == StartAnchor )
_eState = EndAnchor;
else
_eState = StartAnchor;

SCODE sc = SwitchToNextHtmlElement( pStat );

return sc;
}



//+-------------------------------------------------------------------------
//
// Method: CAnchorTag::GetText
//
// Synopsis: Retrieves text from current chunk
//
// Arguments: [pcwcOutput] -- count of UniCode characters in buffer
// [awcBuffer] -- buffer for text
//
//--------------------------------------------------------------------------

SCODE CAnchorTag::GetText( ULONG *pcwcOutput, WCHAR *awcBuffer )
{
if ( _eState == StartAnchor )
{
*pcwcOutput = 0;
return FILTER_E_NO_MORE_TEXT;
}

ULONG cCharsRemaining = _cHrefChars - _cHrefCharsFiltered;

if ( cCharsRemaining == 0 )
{
*pcwcOutput = 0;
return FILTER_E_NO_MORE_TEXT;
}

if ( *pcwcOutput < cCharsRemaining )
{
RtlCopyMemory( awcBuffer,
_pwcHrefBuf + _cHrefCharsFiltered,
*pcwcOutput * sizeof(WCHAR) );
_cHrefCharsFiltered += *pcwcOutput;

return S_OK;
}
else
{
RtlCopyMemory( awcBuffer,
_pwcHrefBuf + _cHrefCharsFiltered,
cCharsRemaining * sizeof(WCHAR) );
_cHrefCharsFiltered += cCharsRemaining;
*pcwcOutput = cCharsRemaining;

return FILTER_S_LAST_TEXT;
}
}



//+-------------------------------------------------------------------------
//
// Method: CAnchorTag::InitStatChunk
//
// Synopsis: Initializes the STAT_CHUNK
//
// Arguments: [pStat] -- STAT_CHUNK to initialize
//
//--------------------------------------------------------------------------

void CAnchorTag::InitStatChunk( STAT_CHUNK *pStat )
{
pStat->idChunk = _htmlIFilter.GetNextChunkId();
pStat->flags = CHUNK_TEXT;
pStat->locale = _htmlIFilter.GetLocale();
pStat->attribute.guidPropSet = CLSID_HtmlInformation;
pStat->attribute.psProperty.ulKind = PRSPEC_PROPID;
pStat->attribute.psProperty.propid = PID_HREF;
pStat->breakType = CHUNK_EOS;

if ( _eState == StartAnchor)
{
//
// Start tag, hence read href field into local buffer
//
_scanner.ReadTagIntoBuffer();

WCHAR *pwcHrefBuf;
unsigned cHrefChars;
_scanner.ScanTagBuffer( L"href=\"", pwcHrefBuf, cHrefChars );

//
// Need to grow internal buffer ?
//
if ( cHrefChars > _uLenHrefBuf )
{
delete[] _pwcHrefBuf;
_pwcHrefBuf = 0;
_uLenHrefBuf = 0;

_pwcHrefBuf = newk(mtNewX, NULL) WCHAR[cHrefChars];
_uLenHrefBuf = cHrefChars;
}

RtlCopyMemory( _pwcHrefBuf, pwcHrefBuf, cHrefChars*sizeof(WCHAR) );
_cHrefChars = cHrefChars;
_cHrefCharsFiltered = 0;

pStat->idChunkSource = 0;
pStat->cwcStartSource = 0;
pStat->cwcLenSource = 0;
}
else
{
Win4Assert( _eState == EndAnchor );

_scanner.EatTag();

//
// Set up the filter region to be the one between the start and end
// anchor tags, i.e. the region belonging to the current Html element,
// because we haven't changed state yet.
//
_htmlIFilter.GetCurHtmlElement()->InitFilterRegion( pStat->idChunkSource,
pStat->cwcStartSource,
pStat->cwcLenSource );
}
}