*! Close any previously opened 'm' tag before opening another one.

This commit is contained in:
Konstantin Isakov 2009-05-07 14:54:26 +00:00
parent cb512b9b11
commit 44b5524a91
2 changed files with 85 additions and 68 deletions

View file

@ -134,6 +134,12 @@ ArticleDom::ArticleDom( wstring const & str ):
if ( !isClosing ) if ( !isClosing )
{ {
if ( name.size() == 2 && name[ 0 ] == L'm' && iswdigit( name[ 1 ] ) )
{
// Opening an 'mX' tag closes any previous 'm' tag
closeTag( GD_NATIVE_TO_WS( L"m" ), stack, false );
}
Node node( Node::Tag(), name, attrs ); Node node( Node::Tag(), name, attrs );
if ( stack.empty() ) if ( stack.empty() )
@ -149,74 +155,7 @@ ArticleDom::ArticleDom( wstring const & str ):
} }
else else
{ {
// Find the tag which is to be closed closeTag( name, stack );
list< Node * >::reverse_iterator n;
for( n = stack.rbegin(); n != stack.rend(); ++n )
{
if ( (*n)->tagName == name || checkM( (*n)->tagName, name ) )
{
// Found it
break;
}
}
if ( n != stack.rend() )
{
// If there is a corresponding tag, close all tags above it,
// then close the tag itself, then reopen all the tags which got
// closed.
list< Node > nodesToReopen;
while( stack.size() )
{
bool found = stack.back()->tagName == name ||
checkM( stack.back()->tagName, name );
if ( !found )
nodesToReopen.push_back( Node( Node::Tag(), stack.back()->tagName,
stack.back()->tagAttrs ) );
if ( stack.back()->empty() )
{
// Empty nodes are deleted since they're no use
stack.pop_back();
Node * parent = stack.size() ? stack.back() : &root;
parent->pop_back();
}
else
stack.pop_back();
if ( found )
break;
}
while( nodesToReopen.size() )
{
if ( stack.empty() )
{
root.push_back( nodesToReopen.back() );
stack.push_back( &root.back() );
}
else
{
stack.back()->push_back( nodesToReopen.back() );
stack.push_back( &stack.back()->back() );
}
nodesToReopen.pop_back();
}
}
else
{
fprintf( stderr, "Warning: no corresponding opening tag for closing tag \"/%ls\" found.\n",
name.c_str() );
}
} // if ( isClosing ) } // if ( isClosing )
continue; continue;
} // if ( ch == '[' ) } // if ( ch == '[' )
@ -401,6 +340,81 @@ ArticleDom::ArticleDom( wstring const & str ):
fprintf( stderr, "Warning: %u tags were unclosed.\n", stack.size() ); fprintf( stderr, "Warning: %u tags were unclosed.\n", stack.size() );
} }
void ArticleDom::closeTag( wstring const & name,
list< Node * > & stack,
bool warn )
{
// Find the tag which is to be closed
list< Node * >::reverse_iterator n;
for( n = stack.rbegin(); n != stack.rend(); ++n )
{
if ( (*n)->tagName == name || checkM( (*n)->tagName, name ) )
{
// Found it
break;
}
}
if ( n != stack.rend() )
{
// If there is a corresponding tag, close all tags above it,
// then close the tag itself, then reopen all the tags which got
// closed.
list< Node > nodesToReopen;
while( stack.size() )
{
bool found = stack.back()->tagName == name ||
checkM( stack.back()->tagName, name );
if ( !found )
nodesToReopen.push_back( Node( Node::Tag(), stack.back()->tagName,
stack.back()->tagAttrs ) );
if ( stack.back()->empty() )
{
// Empty nodes are deleted since they're no use
stack.pop_back();
Node * parent = stack.size() ? stack.back() : &root;
parent->pop_back();
}
else
stack.pop_back();
if ( found )
break;
}
while( nodesToReopen.size() )
{
if ( stack.empty() )
{
root.push_back( nodesToReopen.back() );
stack.push_back( &root.back() );
}
else
{
stack.back()->push_back( nodesToReopen.back() );
stack.push_back( &stack.back()->back() );
}
nodesToReopen.pop_back();
}
}
else
if ( warn )
{
fprintf( stderr, "Warning: no corresponding opening tag for closing tag \"/%ls\" found.\n",
name.c_str() );
}
}
void ArticleDom::nextChar() throw( eot ) void ArticleDom::nextChar() throw( eot )
{ {
if ( !*stringPos ) if ( !*stringPos )

View file

@ -68,6 +68,9 @@ struct ArticleDom
private: private:
void closeTag( wstring const & name, list< Node * > & stack,
bool warn = true );
wchar const * stringPos; wchar const * stringPos;
class eot {}; class eot {};