#include "kdebug.h"
#include "css_base.h"
#ifdef CSS_DEBUG
#include "cssproperties.h"
#endif
#include "css_stylesheetimpl.h"
#include "xml/dom_docimpl.h"
#include "misc/htmlhashes.h"
#include "css_valueimpl.h"
using namespace DOM;
void StyleBaseImpl::checkLoaded()
{
if(m_parent) m_parent->checkLoaded();
}
StyleSheetImpl* StyleBaseImpl::stylesheet()
{
StyleBaseImpl *b = this;
while(b && !b->isStyleSheet())
b = b->m_parent;
return static_cast<StyleSheetImpl *>(b);
}
DOMString StyleBaseImpl::baseURL()
{
StyleSheetImpl *sheet = stylesheet();
if(!sheet) return DOMString();
if(!sheet->href().isNull())
return sheet->href();
if(sheet->parent()) return sheet->parent()->baseURL();
if(!sheet->ownerNode()) return DOMString();
DocumentImpl *doc = sheet->ownerNode()->getDocument();
return doc->baseURL();
}
StyleListImpl::~StyleListImpl()
{
StyleBaseImpl *n;
if(!m_lstChildren) return;
for( n = m_lstChildren->first(); n != 0; n = m_lstChildren->next() )
{
n->setParent(0);
if( !n->refCount() ) delete n;
}
delete m_lstChildren;
}
void CSSSelector::print(void)
{
kdDebug( 6080 ) << "[Selector: tag = " << tag << ", attr = \"" << attr << "\", match = \"" << match
<< "\" value = \"" << value.string().latin1() << "\" relation = " << (int)relation
<< "]" << endl;
if ( tagHistory )
tagHistory->print();
kdDebug( 6080 ) << " specificity = " << specificity() << endl;
}
unsigned int CSSSelector::specificity()
{
int s = ((localNamePart(tag) == anyLocalName) ? 0 : 1);
switch(match)
{
case Id:
s += 0x10000;
break;
case Exact:
case Class:
case Set:
case List:
case Hyphen:
case Pseudo:
case Contain:
case Begin:
case End:
s += 0x100;
case None:
break;
}
if(tagHistory)
s += tagHistory->specificity();
return s & 0xffffff;
}
void CSSSelector::extractPseudoType() const
{
if (match != Pseudo)
return;
static AtomicString active("active");
static AtomicString after("after");
static AtomicString anyLink("-khtml-any-link");
static AtomicString before("before");
static AtomicString drag("-khtml-drag");
static AtomicString empty("empty");
static AtomicString firstChild("first-child");
static AtomicString firstLetter("first-letter");
static AtomicString firstLine("first-line");
static AtomicString focus("focus");
static AtomicString hover("hover");
static AtomicString link("link");
static AtomicString lang("lang(");
static AtomicString lastChild("last-child");
static AtomicString notStr("not(");
static AtomicString onlyChild("only-child");
static AtomicString root("root");
static AtomicString selection("selection");
static AtomicString target("target");
static AtomicString visited("visited");
_pseudoType = PseudoOther;
if (value == active)
_pseudoType = PseudoActive;
else if (value == after)
_pseudoType = PseudoAfter;
else if (value == anyLink)
_pseudoType = PseudoAnyLink;
else if (value == before)
_pseudoType = PseudoBefore;
else if (value == drag)
_pseudoType = PseudoDrag;
else if (value == empty)
_pseudoType = PseudoEmpty;
else if (value == firstChild)
_pseudoType = PseudoFirstChild;
else if (value == firstLetter)
_pseudoType = PseudoFirstLetter;
else if (value == firstLine)
_pseudoType = PseudoFirstLine;
else if (value == focus)
_pseudoType = PseudoFocus;
else if (value == hover)
_pseudoType = PseudoHover;
else if (value == link)
_pseudoType = PseudoLink;
else if (value == lang)
_pseudoType = PseudoLang;
else if (value == lastChild)
_pseudoType = PseudoLastChild;
else if (value == notStr)
_pseudoType = PseudoNot;
else if (value == onlyChild)
_pseudoType = PseudoOnlyChild;
else if (value == root)
_pseudoType = PseudoRoot;
else if (value == selection)
_pseudoType = PseudoSelection;
else if (value == target)
_pseudoType = PseudoTarget;
else if (value == visited)
_pseudoType = PseudoVisited;
value = nullAtom;
}
bool CSSSelector::operator == ( const CSSSelector &other )
{
const CSSSelector *sel1 = this;
const CSSSelector *sel2 = &other;
while ( sel1 && sel2 ) {
if ( sel1->tag != sel2->tag || sel1->attr != sel2->attr ||
sel1->relation != sel2->relation || sel1->match != sel2->match ||
sel1->value != sel2->value ||
sel1->pseudoType() != sel2->pseudoType())
return false;
sel1 = sel1->tagHistory;
sel2 = sel2->tagHistory;
}
if ( sel1 || sel2 )
return false;
return true;
}
DOMString CSSSelector::selectorText() const
{
DOMString str;
const CSSSelector* cs = this;
Q_UINT16 tag = localNamePart(cs->tag);
if ( tag == anyLocalName && cs->attr == ATTR_ID && cs->match == CSSSelector::Exact )
{
str = "#";
str += cs->value.string();
}
else if ( tag == anyLocalName && cs->attr == ATTR_CLASS && cs->match == CSSSelector::Class )
{
str = ".";
str += cs->value.string();
}
else if ( tag == anyLocalName && cs->match == CSSSelector::Pseudo )
{
str = ":";
str += cs->value.string();
}
else
{
if ( tag == anyLocalName )
str = "*";
else
str = getTagName( cs->tag );
if ( cs->attr == ATTR_ID && cs->match == CSSSelector::Exact )
{
str += "#";
str += cs->value.string();
}
else if ( cs->attr == ATTR_CLASS && cs->match == CSSSelector::Class )
{
str += ".";
str += cs->value.string();
}
else if ( cs->match == CSSSelector::Pseudo )
{
str += ":";
str += cs->value.string();
}
if ( cs->attr ) {
DOMString attrName = getAttrName( cs->attr );
str += "[";
str += attrName;
switch (cs->match) {
case CSSSelector::Exact:
str += "=";
break;
case CSSSelector::Set:
str += " "; break;
case CSSSelector::List:
str += "~=";
break;
case CSSSelector::Hyphen:
str += "|=";
break;
case CSSSelector::Begin:
str += "^=";
break;
case CSSSelector::End:
str += "$=";
break;
case CSSSelector::Contain:
str += "*=";
break;
default:
kdWarning(6080) << "Unhandled case in CSSStyleRuleImpl::selectorText : match=" << cs->match << endl;
}
str += "\"";
str += cs->value.string();
str += "\"]";
}
}
if ( cs->tagHistory ) {
DOMString tagHistoryText = cs->tagHistory->selectorText();
if ( cs->relation == Sibling )
str = tagHistoryText + " + " + str;
else if ( cs->relation == Child )
str = tagHistoryText + " > " + str;
else if ( cs->relation == SubSelector )
str += tagHistoryText; else str = tagHistoryText + " " + str;
}
return str;
}