Skip to content

Commit

Permalink
css
Browse files Browse the repository at this point in the history
  • Loading branch information
Vadim Lopatin committed Dec 12, 2007
1 parent 2a8a198 commit 3cd5ec4
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 15 deletions.
1 change: 1 addition & 0 deletions trunk/include/fb2def.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ XS_END_TAGS
XS_BEGIN_ATTRS

XS_ATTR( id )
XS_ATTR( class )
XS_ATTR( value )
XS_ATTR( name )
XS_ATTR( number )
Expand Down
1 change: 1 addition & 0 deletions trunk/include/lvstsheet.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ enum LVCssSelectorRuleType
cssrt_attrhas, // E[foo~="value"]
cssrt_attrstarts, // E[foo|="value"]
cssrt_id, // E#id
cssrt_class, // E.class
};

class LVCssSelectorRule
Expand Down
20 changes: 20 additions & 0 deletions trunk/include/lvtinydom.h
Original file line number Diff line number Diff line change
Expand Up @@ -653,6 +653,24 @@ class ldomXPointerEx : public ldomXPointer
void recurseElements( void (*pFun)( ldomXPointerEx & node ) );
/// calls specified function recursively for all nodes of DOM tree
void recurseNodes( void (*pFun)( ldomXPointerEx & node ) );
/// set new offset value
void setOffset( int offset )
{
_offset = offset;
}
};

class ldomXRange;

/// callback for DOM tree iteration interface
class ldomNodeCallback {
public:
/// destructor
virtual ~ldomNodeCallback() { }
/// called for each found text fragment in range
virtual void onText( ldomXRange * nodeRange ) = 0;
/// called for each found node in range
virtual bool onElement( ldomXPointerEx * ptr ) = 0;
};

/// DOM range
Expand Down Expand Up @@ -721,6 +739,8 @@ class ldomXRange {
lString16 getRangeText( lChar16 blockDelimiter=0, int maxTextLen=0 );
/// sets range to nearest word bounds, returns true if success
static bool getWordRange( ldomXRange & range, ldomXPointer & p );
/// run callback for each node in range
void forEach( ldomNodeCallback * callback );
};

class ldomMarkedText
Expand Down
46 changes: 42 additions & 4 deletions trunk/src/lvstsheet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "../include/lvstsheet.h"
#include "../include/lvtinydom.h"
#include "../include/fb2def.h"

enum css_decl_code {
cssd_unknown,
Expand Down Expand Up @@ -778,6 +779,21 @@ bool LVCssSelectorRule::check( const ldomNode * & node )
break;
case cssrt_id: // E#id
// todo
{
lString16 val = node->getAttributeValue(attr_id);
if (_value.length()>val.length())
return false;
return val == _value;
}
break;
case cssrt_class: // E.class
// todo
{
lString16 val = node->getAttributeValue(attr_class);
if (_value.length()>val.length())
return false;
return val == _value;
}
break;
case cssrt_universal: // *
return true;
Expand Down Expand Up @@ -848,16 +864,38 @@ bool parse_attr_value( const char * &str, char * buf )

LVCssSelectorRule * parse_attr( const char * &str, lxmlDocBase * doc )
{
char attrname[64];
char attrvalue[64];
LVCssSelectorRuleType st = cssrt_universal;
if (*str != '[')
if (*str=='.') {
// E.class
str++;
skip_spaces( str );
if (!parse_ident( str, attrvalue ))
return NULL;
skip_spaces( str );
LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_class);
lString16 s( attrvalue );
rule->setAttr(attr_class, s);
return rule;
} else if ( *str=='#' ) {
// E#id
str++;
skip_spaces( str );
if (!parse_ident( str, attrvalue ))
return NULL;
skip_spaces( str );
LVCssSelectorRule * rule = new LVCssSelectorRule(cssrt_id);
lString16 s( attrvalue );
rule->setAttr(attr_id, s);
return rule;
} else if (*str != '[')
return NULL;
str++;
skip_spaces( str );
char attrname[64];
if (!parse_ident( str, attrname ))
return NULL;
skip_spaces( str );
char attrvalue[64];
attrvalue[0] = 0;
if (*str==']')
{
Expand Down Expand Up @@ -932,7 +970,7 @@ bool LVCssSelector::parse( const char * &str, lxmlDocBase * doc )
return true;
// one or more attribute rules
bool attr_rule = false;
while ( *str == '[' )
while ( *str == '[' || *str=='.' || *str=='#' )
{
LVCssSelectorRule * rule = parse_attr( str, doc );
if (!rule)
Expand Down
118 changes: 107 additions & 11 deletions trunk/src/lvtinydom.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2212,18 +2212,114 @@ bool ldomXRange::getWordRange( ldomXRange & range, ldomXPointer & p )
return true;
}

/// returns text between two XPointer positions
lString16 ldomXRange::getRangeText( lChar16 blockDelimiter, int maxTextLen )
/// run callback for each node in range
void ldomXRange::forEach( ldomNodeCallback * callback )
{
ldomXPointerEx pos( _start );
ldomXPointerEx endpos( _end );
lString16 res;
if ( pos.getNode() == endpos.getNode() ) {
if ( pos.getOffset() >= endpos.getOffset() )
return res;
if ( pos.getNode()->getNodeType()==LXML_TEXT_NODE ) {
return pos.getNode()->getText().substr( pos.getOffset(), endpos.getOffset()-pos.getOffset() );
if ( isNull() )
return;
ldomXRange pos( _start, _end, 0 );
bool allowGoRecurse = true;
while ( pos._start.compare( _end ) < 0 ) {
// do something
ldomNode * node = pos._start.getNode();
if ( node->getNodeType()==LXML_ELEMENT_NODE ) {
allowGoRecurse = callback->onElement( &pos.getStart() );
} else if ( node->getNodeType()==LXML_TEXT_NODE ) {
lString16 txt = node->getText();
pos._end = pos._start;
pos._start.setOffset( 0 );
pos._end.setOffset( txt.length() );
if ( _start.getNode() == node ) {
pos._start.setOffset( _start.getOffset() );
}
if ( _end.getNode() == node && pos._end.getOffset() > _end.getOffset()) {
pos._end.setOffset( _end.getOffset() );
}
callback->onText( &pos );
allowGoRecurse = false;
}
// move to next item
if ( !allowGoRecurse || !pos._start.child(0) ) {
while ( !pos._start.nextSibling() ) {
if ( !pos._start.parent() )
break;
}
}
}
return res;
}

class ldomTextCollector : public ldomNodeCallback
{
private:
bool lastText;
bool newBlock;
int delimiter;
int maxLen;
lString16 text;
public:
ldomTextCollector( lChar16 blockDelimiter, int maxTextLen )
: lastText(false), newBlock(true), delimiter( blockDelimiter), maxLen( maxTextLen )
{
}
/// destructor
virtual ~ldomTextCollector() { }
/// called for each found text fragment in range
virtual void onText( ldomXRange * nodeRange )
{
if ( newBlock && !text.empty()) {
text << delimiter;
}
lString16 txt = nodeRange->getStart().getNode()->getText();
int start = nodeRange->getStart().getOffset();
int end = nodeRange->getEnd().getOffset();
if ( start < end ) {
text << txt.substr( start, end-start );
}
lastText = true;
newBlock = false;
}
/// called for each found node in range
virtual bool onElement( ldomXPointerEx * ptr )
{
ldomElement * elem = (ldomElement *)ptr->getNode();
if ( elem->getRendMethod()==erm_invisible )
return false;
switch ( elem->getStyle()->display ) {
/*
case css_d_inherit:
case css_d_block:
case css_d_list_item:
case css_d_compact:
case css_d_marker:
case css_d_table:
case css_d_inline_table:
case css_d_table_row_group:
case css_d_table_header_group:
case css_d_table_footer_group:
case css_d_table_row:
case css_d_table_column_group:
case css_d_table_column:
case css_d_table_cell:
case css_d_table_caption:
*/
default:
newBlock = true;
case css_d_none:
return false;
case css_d_inline:
case css_d_run_in:
newBlock = false;
return true;
}
}
/// get collected text
lString16 getText() { return text; }
};

/// returns text between two XPointer positions
lString16 ldomXRange::getRangeText( lChar16 blockDelimiter, int maxTextLen )
{
ldomTextCollector callback( blockDelimiter, maxTextLen );
forEach( &callback );
return callback.getText();
}

0 comments on commit 3cd5ec4

Please sign in to comment.