📄 htmlparse.cpp
字号:
case pVAlign:
valg = GetAlignmentFromString( strParam, valg );
break;
}
}
if( m_stkTable.GetSize() )
{
m_stkTable.Top()->NewRow( valg );
}
}
void CHTMLParse::OnGotTableCell( const CParameters &pList )
{
// Ensure that we are processing documents properly.
// close the previous cell if it was left open...
if (m_stkInTableCell.GetSize())
{
if (m_stkInTableCell.Top())
OnGotEndTableCell();
m_stkInTableCell.Top() = true;
}
int nWidth = 0;
int nHeight = 0;
bool bNoWrap = false;
bool bTransparent = true;
COLORREF crBorder = RGB(0,0,0);
COLORREF crBgColor = RGB( 255, 255, 255 ); // Not really used.
COLORREF crBorderLight = m_pDefaults->m_crBorderLight;
COLORREF crBorderDark = m_pDefaults->m_crBorderDark;
bool bBorderDarkSet = false;
bool bBorderLightSet = false;
CHTMLParse::Align alg = knDefaultTableCellAlignment;
CHTMLParse::Align valg = m_stkTable.Top()->GetCurrentRow()->m_valg;
// Get defaults from the current table
// Could really ignore everything if we are not in a table!
if( m_stkTable.GetSize() )
{
CHTMLTable* pTab = m_stkTable.Top();
crBorderLight = pTab->m_crBorderLight;
crBorderDark = pTab->m_crBorderDark;
}
const UINT uParamSize = pList.GetSize();
for( UINT n = 0; n < uParamSize; n++ )
{
const CStaticString &strParam = pList[n].m_strValue;
switch( pList[n].m_param )
{
case pWidth:
nWidth = GetNumberParameterPercent( strParam, nWidth );
break;
case pHeight:
nHeight = GetNumberParameter( strParam, nHeight );
break;
case pAlign:
alg = GetAlignmentFromString( strParam, alg );
break;
case pVAlign:
valg = GetAlignmentFromString( strParam, alg );
break;
// richg - 19990224 - Add support for NOWRAP
case pNoWrap:
bNoWrap = true;
break;
case pBColor:
crBgColor = GetColourFromString( strParam, crBgColor );
bTransparent = false;
break;
case pBorderColor:
crBorder = GetColourFromString( strParam, crBorder );
if ( !bBorderDarkSet )
crBorderDark = crBorder;
if ( !bBorderLightSet )
crBorderLight = crBorder;
break;
case pBorderColorLight:
crBorderLight = GetColourFromString( strParam, crBorderLight );
bBorderLightSet = true;
break;
case pBorderColorDark:
crBorderDark = GetColourFromString( strParam, crBorderDark );
bBorderDarkSet = true;
break;
}
}
//
// If there is a table to add our cell to...
if( m_stkTable.GetSize() )
{
CHTMLTableCell *pCell = new CHTMLTableCell( m_pDefaults, nWidth, nHeight, bNoWrap, bTransparent, crBgColor, crBorderDark, crBorderLight, valg );
// Copy the current documents link colors into the new document
pCell->m_crLink = m_pDocument->m_crLink;
pCell->m_crLinkHover = m_pDocument->m_crLinkHover;
// Push it onto the document stack
m_stkDocument.Push( m_pDocument );
// TRACENL("Document Stack Pushed. %d\n", m_stkDocument.GetSize());
m_pDocument = pCell;
m_pProp->nAlignment = alg;
CreateNewParagraph( 0, 0, m_pProp->nAlignment );
m_stkTable.Top()->AddCell( pCell );
}
}
void CHTMLParse::OnGotEndTableCell()
{
CreateNewTextObject();
if( m_stkDocument.GetSize() )
{
m_pDocument = m_stkDocument.Pop();
// TRACENL("Document Stack Popped. %d\n", m_stkDocument.GetSize());
}
else
{
TRACE( _T("Got an end table cell but no document stack left\n") );
}
if (m_stkInTableCell.GetSize())
m_stkInTableCell.Top() = false;
}
void CHTMLParse::OnGotEndTableRow()
{
if( m_stkInTableCell.GetSize() && m_stkInTableCell.Top() )
OnGotEndTableCell();
}
void CHTMLParse::CreateList( bool bOrdered )
{
CreateNewTextObject();
CreateNewParagraph( 0, 0, CHTMLParse::algLeft );
CHTMLList *pList = new CHTMLList( bOrdered );
m_stkList.Push( pList );
m_pDocument->CurrentParagraph()->AddItem( m_stkList.Top() );
// Create the default first item
CHTMLListItem *pItem = new CHTMLListItem( m_pDefaults, false, m_pProp->szFaceName, m_pProp->nSize, m_pProp->bBold, m_pProp->bItalic, m_pProp->bUnderline, m_pProp->bStrikeThrough, m_pProp->m_crFore ); // Not bulleted
// Copy the current documents link colors into the new document
pItem->m_crLink = m_pDocument->m_crLink;
pItem->m_crLinkHover = m_pDocument->m_crLinkHover;
m_stkDocument.Push( m_pDocument );
m_pDocument = pItem;
CreateNewParagraph( 0, 0, CHTMLParse::algLeft );
m_stkList.Top()->AddItem( pItem );
}
void CHTMLParse::OnGotUnorderedList( const CParameters & /* pList */ )
{
CreateList( false );
}
void CHTMLParse::OnGotOrderedList( const CParameters & /* pList */ )
{
CreateList( true );
}
void CHTMLParse::OnGotListItem( const CParameters & /* pList */ )
{
// </li> is completely ignored by IE4, and by NetScape
// Additionally, items occuring after the <ol> or <ul> and
// before the first <li> are positioned as if they were preceeded
// by <li>, but the bullet is not shown. Empty <LI> tags DO show their
// bullets.
// In order to handle these cases, do the following:
// For a new list, create the initial list item, but flag it as
// unbulleted. When a <LI> is reached, determine if there is
// exactly one item in the list. If so, and it is empty, Mark the
// existing item as bulleted, and use it... otherwise, proceed by adding
// another list item.
// See that we are in a list, otherwise, ignore it...
if ( m_stkList.GetSize() )
{
CreateNewTextObject();
// See if we can use the existing item
if ( m_stkList.Top()->m_arrItems.GetSize() == 1 &&
!m_stkList.Top()->m_arrItems[0]->m_bBullet &&
m_stkList.Top()->m_arrItems[0]->IsEmpty() )
{
// There is en emptry entry that is not bulleted
m_stkList.Top()->m_arrItems[0]->m_bBullet = true;
// Nothing more to do!
return;
}
// We are in a list and creating a new item, close the previous item
CreateNewTextObject();
if( m_stkDocument.GetSize() )
{
m_pDocument = m_stkDocument.Pop();
}
// Need to create a new item...
CHTMLListItem *pItem = new CHTMLListItem( m_pDefaults, true, m_pProp->szFaceName, m_pProp->nSize, m_pProp->bBold, m_pProp->bItalic, m_pProp->bUnderline, m_pProp->bStrikeThrough, m_pProp->m_crFore ); // bulleted
// Copy the current documents link colors into the new document
pItem->m_crLink = m_pDocument->m_crLink;
pItem->m_crLinkHover = m_pDocument->m_crLinkHover;
m_stkDocument.Push( m_pDocument );
m_pDocument = pItem;
CreateNewParagraph( 0, 0, CHTMLParse::algLeft );
m_stkList.Top()->AddItem( pItem );
}
}
void CHTMLParse::OnGotEndListItem()
{
// Do nothing.
}
void CHTMLParse::OnGotEndList()
{
// See that we are in a list, otherwise, ignore it...
if ( m_stkList.GetSize() )
{
// Close the last item...
CreateNewTextObject();
if( m_stkDocument.GetSize() )
{
m_pDocument = m_stkDocument.Pop();
}
CreateNewParagraph( 0, 0, CHTMLParse::algLeft );
// Close this list.
m_stkList.Pop();
}
}
void CHTMLParse::OnGotBlockQuote( const CParameters & /* pList */ )
{
/*
A Blockquote is treated as a sub document with different
margins. This is fairly straightforward.
*/
CreateNewTextObject();
CreateNewParagraph( 0, 0, m_pProp->nAlignment );
CHTMLBlockQuote *pBQ = new CHTMLBlockQuote( m_pDefaults );
m_pDocument->CurrentParagraph()->AddItem( pBQ );
// Make the sub document the main document
m_stkDocument.Push( m_pDocument );
m_pDocument = pBQ->m_pDoc;
CreateNewParagraph( 0, 0, m_pProp->nAlignment);
}
void CHTMLParse::OnGotEndBlockQuote()
{
/*
Cause a document stack pop if possible...
*/
CreateNewTextObject();
if( m_stkDocument.GetSize() )
{
m_pDocument = m_stkDocument.Pop();
}
else
{
TRACE( _T("At </BLOCKQUOTE> but document stack is empty.\n") );
}
CreateNewParagraph(0, 0, m_pProp->nAlignment);
}
void CHTMLParse::OnGotAddress( const CParameters & /* pList */ )
//
// Fundtionally the same as BLOCKQUOTE but with italics
{
CreateNewTextObject();
CreateNewParagraph( 0, 0, m_pProp->nAlignment );
CreateNewProperties();
m_pProp->bItalic = true;
CHTMLBlockQuote *pBQ = new CHTMLBlockQuote( m_pDefaults );
m_pDocument->CurrentParagraph()->AddItem( pBQ );
// Make the sub document the main document
m_stkDocument.Push( m_pDocument );
m_pDocument = pBQ->m_pDoc;
CreateNewParagraph( 0, 0, m_pProp->nAlignment);
}
void CHTMLParse::OnGotEndAddress()
{
CreateNewTextObject();
if( m_stkDocument.GetSize() )
{
m_pDocument = m_stkDocument.Pop();
}
else
{
TRACE( _T("At </BLOCKQUOTE> but document stack is empty.\n") );
}
PopPreviousProperties();
CreateNewParagraph(0, 0, m_pProp->nAlignment);
}
void CHTMLParse::GetFontName( LPTSTR pszBuffer, int nBufferSize, const CStaticString &strFontNameSpec )
//
// Get the font name from a font name spec.
// This consists of comma delimited font names "tahoma,arial,helvetica"
// We need to find
{
static const TCHAR cComma = _T(',');
if( strFontNameSpec.GetData() )
{
LPCTSTR pcszFontNameSpec = strFontNameSpec.GetData();
// Set our string to empty
*pszBuffer = _T('\000');
if( strFontNameSpec.Find( cComma ) )
{
//
// Iterate over the passed font names, copying each font name as we go.
LPCTSTR pcszFontNameSpecEnd = strFontNameSpec.GetEndPointer();
LPCTSTR pszFontNameStart, pszFontNameEnd;
pszFontNameStart = pszFontNameEnd = pcszFontNameSpec;
while( pszFontNameStart < pcszFontNameSpecEnd )
{
//
// Find the end of the first font.
while( pszFontNameEnd < pcszFontNameSpecEnd && *pszFontNameEnd != cComma )
pszFontNameEnd++;
if( pszFontNameEnd - pszFontNameStart && pszFontNameEnd - pszFontNameStart < nBufferSize)
{
StringClass strFontName( pszFontNameStart, pszFontNameEnd - pszFontNameStart );
//
// We have our font name, now determine whether the font exists or not.
if( DoesFontExist( strFontName ) )
{
// It does, then we get out of here. If the font doesn't exist then we simply
// continue looping around.
_tcscpy( pszBuffer, strFontName );
return;
}
}
//
// Skip past the white space and commas
while( pszFontNameEnd < pcszFontNameSpecEnd && ( isspace( *pszFontNameEnd ) || *pszFontNameEnd == cComma ) )
pszFontNameEnd++;
pszFontNameStart = pszFontNameEnd;
}
}
else
{
StringClass strFontName( strFontNameSpec.GetData(), strFontNameSpec.GetLength() );
if( DoesFontExist( strFontName ) )
{
// It does, then we get out of here. If the font doesn't exist then we simply
// continue looping around.
_tcscpy( pszBuffer, strFontName );
}
else
{
_tcscpy( pszBuffer, m_pDefaults->m_strFontName );
}
}
}
else
{
_tcscpy( pszBuffer, m_pDefaults->m_strFontName );
}
//
// If we drop out here it means that none of the user requested fonts exist on the system.
}
static int CALLBACK EnumFontFamExProc( ENUMLOGFONTEX * /*lpelfe*/, NEWTEXTMETRICEX * /*lpntme*/, int /*FontType*/, LPARAM /*lParam*/ )
{
return -1;
}
bool CHTMLParse::DoesFontExist( const StringClass &strFontName )
//
// Determine if the font exists in our map and return that result.
// If it doesn't exist in our map then ask the system if the font exists and add
// that known state to our map.
{
bool *pb = g_mapFontName.Lookup( strFontName );
if( pb )
{
return *pb;
}
LOGFONT lf = { 0 };
_tcscpy( lf.lfFaceName, strFontName );
lf.lfCharSet = m_pMasterDocument->m_cCharSet;
CDrawContext dc;
bool bExists = false;
//
// NOTE: If the font doesn't exist EnumFontFamiliesEx returns 1 - originally I had my callbcak return
// true or false. This didn't work if the font didn't exist. Now the callback returns -1 if the font
// exists.
if( EnumFontFamiliesEx( dc.GetSafeHdc(), &lf, (FONTENUMPROC)EnumFontFamExProc, 0, 0 ) == -1 )
bExists = true;
g_mapFontName.SetAt( strFontName, bExists );
#ifdef _DEBUG
if( !bExists )
{
TRACE( "Font doesn't exist '%s'\n", strFontName );
}
#endif // _DEBUG
return bExists;
}
void CHTMLParse::OnGotMeta( const CParameters &pList )
{
const UINT uParamSize = pList.GetSize();
for( UINT n = 0; n < uParamSize; n++ )
{
const CStaticString &strParam = pList[n].m_strValue;
switch( pList[n].m_param )
{
case pContent:
{
LPCTSTR pcszEnd = strParam.GetData() + strParam.GetLength();
static const TCHAR szCharSet[] = _T("charset");
LPCTSTR p = stristr( (LPTSTR)strParam.GetData(), szCharSet );
if( p )
{
//
// We have a charset, so next we need to decode it
p += countof( szCharSet ) - 1;
while( p < pcszEnd && ( isspace( *p ) || *p == _T('=') ) )
p++;
if( p < pcszEnd )
{
const CStaticString str( p, pcszEnd - p );
m_pDocument->m_cCharSet = DecodeCharset( str );
}
}
}
break;
case pHTTPEquiv:
//TRACE( "pHTTPEquiv %s\n", strParam );
break;
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -