Rule matching

David Hyatt hyatt at apple.com
Thu Feb 5 02:44:48 CET 2004


This patch rewrites rule matching in the style system for a fairly 
significant 4-5% perf gain (much more on large CSS pages like the CSS 
pencils page).

This code is new and likely to cause a regression or two, so you may 
want to hold off merging if you're worried about stability at the 
moment.

dave

-------------- next part --------------
Index: ChangeLog
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/ChangeLog,v
retrieving revision 1.2495
diff -u -p -r1.2495 ChangeLog
--- ChangeLog	2004/02/04 22:22:13	1.2495
+++ ChangeLog	2004/02/05 01:40:11
@@ -1,5 +1,180 @@
 2004-02-04  David Hyatt  <hyatt at apple.com>
 
+	Improve rule matching in the style system.  Filter out most rules up front, so that only a small
+	number of rules need to be walked for any given element.  Yields a ~4-5% improvement on the PLT.
+	
+        Reviewed by kocienda
+
+        * khtml/css/css_base.cpp:
+        (StyleBaseImpl::setParsedValue):
+        (CSSSelector::specificity):
+        (CSSSelector::extractPseudoType):
+        (CSSSelector::operator == ):
+        * khtml/css/css_base.h:
+        (DOM::CSSSelector::CSSSelector):
+        (DOM::CSSSelector::~CSSSelector):
+        (DOM::CSSSelector::append):
+        (DOM::CSSSelector::next):
+        (DOM::CSSSelector::):
+        (DOM::StyleBaseImpl::StyleBaseImpl):
+        * khtml/css/css_ruleimpl.cpp:
+        (CSSStyleRuleImpl::selectorText):
+        (CSSRuleListImpl::insertRule):
+        * khtml/css/css_ruleimpl.h:
+        (DOM::CSSStyleRuleImpl::setSelector):
+        (DOM::CSSStyleRuleImpl::selector):
+        * khtml/css/css_stylesheetimpl.cpp:
+        * khtml/css/css_stylesheetimpl.h:
+        * khtml/css/css_valueimpl.cpp:
+        (CSSStyleDeclarationImpl::getPropertyCSSValue):
+        (CSSStyleDeclarationImpl::removeProperty):
+        (CSSStyleDeclarationImpl::setProperty):
+        (CSSStyleDeclarationImpl::setStringProperty):
+        (CSSStyleDeclarationImpl::setImageProperty):
+        (CSSStyleDeclarationImpl::setLengthProperty):
+        (CSSStyleDeclarationImpl::cssText):
+        (CSSStyleDeclarationImpl::setCssText):
+        * khtml/css/css_valueimpl.h:
+        (DOM::CSSStyleDeclarationImpl::node):
+        (DOM::CSSProperty::CSSProperty):
+        (DOM::CSSProperty::id):
+        (DOM::CSSProperty::isImportant):
+        * khtml/css/cssparser.cpp:
+        (CSSParser::CSSParser):
+        (ParseString::lower):
+        (CSSParser::parseValue):
+        (CSSParser::parseDeclaration):
+        (CSSParser::addProperty):
+        (CSSParser::parseShadow):
+        * khtml/css/cssparser.h:
+        * khtml/css/cssstyleselector.cpp:
+        (khtml::):
+        (khtml::CSSStyleSelector::CSSStyleSelector):
+        (khtml::CSSStyleSelector::init):
+        (khtml::CSSStyleSelector::~CSSStyleSelector):
+        (khtml::CSSStyleSelector::loadDefaultStyle):
+        (khtml::CSSStyleSelector::addMatchedRule):
+        (khtml::CSSStyleSelector::addMatchedDeclaration):
+        (khtml::CSSStyleSelector::matchRules):
+        (khtml::CSSStyleSelector::matchRulesForList):
+        (khtml::operator >):
+        (khtml::operator <=):
+        (khtml::CSSStyleSelector::sortMatchedRules):
+        (khtml::CSSStyleSelector::initForStyleResolve):
+        (khtml::CSSStyleSelector::styleForElement):
+        (khtml::CSSStyleSelector::pseudoStyleForElement):
+        (khtml::checkPseudoState):
+        (khtml::CSSStyleSelector::checkSelector):
+        (khtml::CSSStyleSelector::checkOneSelector):
+        (khtml::CSSRuleSet::CSSRuleSet):
+        (khtml::CSSRuleSet::addToRuleSet):
+        (khtml::CSSRuleSet::addRule):
+        (khtml::CSSRuleSet::addRulesFromSheet):
+        (khtml::CSSStyleSelector::applyDeclarations):
+        (khtml::CSSStyleSelector::applyProperty):
+        (khtml::CSSStyleSelector::smallerFontSize):
+        (khtml::CSSStyleSelector::getColorFromPrimitiveValue):
+        * khtml/css/cssstyleselector.h:
+        (khtml::):
+        (khtml::CSSRuleData::m_next):
+        (khtml::CSSRuleData::~CSSRuleData):
+        (khtml::CSSRuleData::position):
+        (khtml::CSSRuleData::rule):
+        (khtml::CSSRuleData::selector):
+        (khtml::CSSRuleData::next):
+        (khtml::CSSRuleDataList::CSSRuleDataList):
+        (khtml::CSSRuleDataList::~CSSRuleDataList):
+        (khtml::CSSRuleDataList::first):
+        (khtml::CSSRuleDataList::last):
+        (khtml::CSSRuleDataList::append):
+        (khtml::CSSRuleSet::~CSSRuleSet):
+        (khtml::CSSRuleSet::getIDRules):
+        (khtml::CSSRuleSet::getClassRules):
+        (khtml::CSSRuleSet::getTagRules):
+        (khtml::CSSRuleSet::getUniversalRules):
+        * khtml/css/cssvalues.c:
+        (hash_val):
+        (findValue):
+        * khtml/css/cssvalues.h:
+        * khtml/css/cssvalues.in:
+        * khtml/css/html4.css:
+        * khtml/css/parser.cpp:
+        * khtml/css/parser.h:
+        * khtml/css/parser.y:
+        * khtml/dom/dom_element.cpp:
+        (Element::style):
+        * khtml/html/html_baseimpl.cpp:
+        (HTMLBodyElementImpl::HTMLBodyElementImpl):
+        (HTMLBodyElementImpl::~HTMLBodyElementImpl):
+        (HTMLBodyElementImpl::createLinkDecl):
+        (HTMLBodyElementImpl::parseAttribute):
+        * khtml/html/html_baseimpl.h:
+        * khtml/html/html_elementimpl.cpp:
+        (HTMLNamedAttrMapImpl::parseClassAttribute):
+        (HTMLElementImpl::HTMLElementImpl):
+        (HTMLElementImpl::~HTMLElementImpl):
+        (HTMLElementImpl::createInlineStyleDecl):
+        (HTMLElementImpl::createMappedAttributeDecl):
+        (HTMLElementImpl::parseAttribute):
+        (HTMLElementImpl::getClassList):
+        (HTMLElementImpl::addCSSProperty):
+        (HTMLElementImpl::addCSSStringProperty):
+        (HTMLElementImpl::addCSSImageProperty):
+        (HTMLElementImpl::addCSSLength):
+        (HTMLElementImpl::addHTMLColor):
+        (HTMLElementImpl::removeCSSProperty):
+        * khtml/html/html_elementimpl.h:
+        (DOM::HTMLNamedAttrMapImpl::getClassList):
+        (DOM::HTMLElementImpl::inlineStyleDecl):
+        (DOM::HTMLElementImpl::attributeStyleDecl):
+        (DOM::HTMLElementImpl::getInlineStyleDecl):
+        * khtml/html/html_tableimpl.cpp:
+        (HTMLTableElementImpl::createSharedCellDecls):
+        (HTMLTableCellElementImpl::additionalAttributeStyleDecl):
+        * khtml/html/html_tableimpl.h:
+        * khtml/xml/dom_atomicstring.cpp:
+        (DOM::AtomicString::add):
+        (DOM::AtomicString::remove):
+        * khtml/xml/dom_docimpl.cpp:
+        (DocumentImpl::DocumentImpl):
+        (DocumentImpl::resetLinkColor):
+        (DocumentImpl::resetVisitedLinkColor):
+        (DocumentImpl::resetActiveLinkColor):
+        (DocumentImpl::recalcStyleSelector):
+        * khtml/xml/dom_docimpl.h:
+        (DOM::DocumentImpl::linkColor):
+        (DOM::DocumentImpl::visitedLinkColor):
+        (DOM::DocumentImpl::activeLinkColor):
+        (DOM::DocumentImpl::setLinkColor):
+        (DOM::DocumentImpl::setVisitedLinkColor):
+        (DOM::DocumentImpl::setActiveLinkColor):
+        * khtml/xml/dom_elementimpl.cpp:
+        (ElementImpl::ElementImpl):
+        (ElementImpl::~ElementImpl):
+        (ElementImpl::getClassList):
+        (ElementImpl::getIDAttribute):
+        (ElementImpl::cloneNode):
+        (XMLElementImpl::cloneNode):
+        * khtml/xml/dom_elementimpl.h:
+        (DOM::ElementImpl::inlineStyleDecl):
+        (DOM::ElementImpl::attributeStyleDecl):
+        (DOM::ElementImpl::getInlineStyleDecl):
+        (DOM::ElementImpl::additionalAttributeStyleDecl):
+        (DOM::NamedAttrMapImpl::id):
+        (DOM::NamedAttrMapImpl::setID):
+        * khtml/xml/dom_stringimpl.cpp:
+        (DOM::DOMStringImpl::DOMStringImpl):
+        (DOM::DOMStringImpl::~DOMStringImpl):
+        (DOM::DOMStringImpl::append):
+        (DOM::DOMStringImpl::insert):
+        (DOM::DOMStringImpl::truncate):
+        (DOM::DOMStringImpl::remove):
+        (DOM::DOMStringImpl::split):
+        * khtml/xml/dom_stringimpl.h:
+        (DOM::DOMStringImpl::DOMStringImpl):
+
+2004-02-04  David Hyatt  <hyatt at apple.com>
+
 	Fix line-height regression on altavista.
 
         * khtml/rendering/render_br.cpp:
Index: khtml/css/css_base.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_base.cpp,v
retrieving revision 1.7
diff -u -p -r1.7 khtml/css/css_base.cpp
--- khtml/css/css_base.cpp	2004/01/30 07:44:44	1.7
+++ khtml/css/css_base.cpp	2004/02/05 01:40:11
@@ -76,12 +76,12 @@ DOMString StyleBaseImpl::baseURL()
 }
 
 void StyleBaseImpl::setParsedValue(int propId, const CSSValueImpl *parsedValue,
-				   bool important, bool nonCSSHint, QPtrList<CSSProperty> *propList)
+				   bool important, QPtrList<CSSProperty> *propList)
 {
     QPtrListIterator<CSSProperty> propIt(*propList);
     propIt.toLast(); // just remove the top one - not sure what should happen if we have multiple instances of the property
     while (propIt.current() &&
-           ( propIt.current()->m_id != propId || propIt.current()->nonCSSHint != nonCSSHint ||
+           ( propIt.current()->m_id != propId ||
              propIt.current()->m_bImportant != important) )
         --propIt;
     if (propIt.current())
@@ -91,8 +91,7 @@ void StyleBaseImpl::setParsedValue(int p
     prop->m_id = propId;
     prop->setValue((CSSValueImpl *) parsedValue);
     prop->m_bImportant = important;
-    prop->nonCSSHint = nonCSSHint;
-
+    
     propList->append(prop);
 #ifdef CSS_DEBUG
     kdDebug( 6080 ) << "added property: " << getPropertyName(propId).string()
@@ -132,9 +131,8 @@ void CSSSelector::print(void)
 
 unsigned int CSSSelector::specificity()
 {
-    if ( nonCSSHint )
-        return 0;
-
+    // FIXME: Pseudo-elements and pseudo-classes do not have the same specificity. This function
+    // isn't quite correct.
     int s = ((localNamePart(tag) == anyLocalName) ? 0 : 1);
     switch(match)
     {
@@ -167,6 +165,7 @@ void CSSSelector::extractPseudoType() co
     
     static AtomicString active("active");
     static AtomicString after("after");
+    static AtomicString anyLink("-khtml-any-link");
     static AtomicString before("before");
     static AtomicString empty("empty");
     static AtomicString firstChild("first-child");
@@ -189,6 +188,8 @@ void CSSSelector::extractPseudoType() co
         _pseudoType = PseudoActive;
     else if (value == after)
         _pseudoType = PseudoAfter;
+    else if (value == anyLink)
+        _pseudoType = PseudoAnyLink;
     else if (value == before)
         _pseudoType = PseudoBefore;
     else if (value == empty)
@@ -234,7 +235,6 @@ bool CSSSelector::operator == ( const CS
     while ( sel1 && sel2 ) {
 	if ( sel1->tag != sel2->tag || sel1->attr != sel2->attr ||
 	     sel1->relation != sel2->relation || sel1->match != sel2->match ||
-	     sel1->nonCSSHint != sel2->nonCSSHint ||
 	     sel1->value != sel2->value ||
              sel1->pseudoType() != sel2->pseudoType())
 	    return false;
Index: khtml/css/css_base.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_base.h,v
retrieving revision 1.4
diff -u -p -r1.4 khtml/css/css_base.h
--- khtml/css/css_base.h	2004/01/27 19:08:33	1.4
+++ khtml/css/css_base.h	2004/02/05 01:40:11
@@ -73,16 +73,22 @@ namespace DOM {
     {
     public:
 	CSSSelector()
-	    : tagHistory(0), simpleSelector(0), attr(0), tag(anyQName),
-              relation( Descendant ), match( None ), nonCSSHint( false ), 
+	    : tagHistory(0), simpleSelector(0), nextSelector(0), attr(0), tag(anyQName),
+              relation( Descendant ), match( None ),
               pseudoId( 0 ), _pseudoType(PseudoNotParsed)
         {}
 
 	~CSSSelector() {
 	    delete tagHistory;
             delete simpleSelector;
+            delete nextSelector;
 	}
 
+        void append(CSSSelector* n) {
+            if (!nextSelector) nextSelector = n; else nextSelector->append(n);
+        }
+        CSSSelector* next() { return nextSelector; }
+
 	/**
 	 * Print debug output for this selector
 	 */
@@ -136,6 +142,7 @@ namespace DOM {
 	    PseudoFirstLetter,
 	    PseudoLink,
 	    PseudoVisited,
+            PseudoAnyLink,
 	    PseudoHover,
 	    PseudoFocus,
 	    PseudoActive,
@@ -156,14 +163,14 @@ namespace DOM {
 	    }
 
 	mutable DOM::AtomicString value;
-	CSSSelector *tagHistory;
+	CSSSelector* tagHistory;
         CSSSelector* simpleSelector; // Used for :not.
+        CSSSelector* nextSelector; // used for ,-chained selectors
 	Q_UINT32     attr;
 	Q_UINT32     tag;
 
         Relation relation     : 2;
 	Match 	 match         : 4;
-	bool	nonCSSHint : 1;
 	unsigned int pseudoId : 3;
 	mutable PseudoType _pseudoType : 5;
 
@@ -175,9 +182,9 @@ namespace DOM {
     class StyleBaseImpl : public khtml::TreeShared<StyleBaseImpl>
     {
     public:
-	StyleBaseImpl()  { m_parent = 0; hasInlinedDecl = false; strictParsing = true; multiLength = false; }
+	StyleBaseImpl()  { m_parent = 0; strictParsing = true; multiLength = false; }
 	StyleBaseImpl(StyleBaseImpl *p) {
-	    m_parent = p; hasInlinedDecl = false;
+	    m_parent = p;
 	    strictParsing = (m_parent ? m_parent->useStrictParsing() : true);
 	    multiLength = false;
 	}
@@ -209,7 +216,7 @@ namespace DOM {
 	void setParent(StyleBaseImpl *parent) { m_parent = parent; }
 
 	static void setParsedValue(int propId, const CSSValueImpl *parsedValue,
-				   bool important, bool nonCSSHint, QPtrList<CSSProperty> *propList);
+				   bool important, QPtrList<CSSProperty> *propList);
 
 	virtual bool parseString(const DOMString &/*cssString*/, bool = false) { return false; }
 
@@ -221,7 +228,6 @@ namespace DOM {
 	StyleSheetImpl* stylesheet();
 
     protected:
-	bool hasInlinedDecl : 1;
 	bool strictParsing : 1;
 	bool multiLength : 1;
     };
Index: khtml/css/css_ruleimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_ruleimpl.cpp,v
retrieving revision 1.13
diff -u -p -r1.13 khtml/css/css_ruleimpl.cpp
--- khtml/css/css_ruleimpl.cpp	2003/08/29 22:04:02	1.13
+++ khtml/css/css_ruleimpl.cpp	2004/02/05 01:40:11
@@ -320,12 +320,9 @@ CSSStyleRuleImpl::~CSSStyleRuleImpl()
 
 DOM::DOMString CSSStyleRuleImpl::selectorText() const
 {
-    if ( m_selector && m_selector->first() ) {
-        // ### m_selector will be a single selector hopefully. so ->first() will disappear
-        CSSSelector* cs = m_selector->first();
-        //cs->print(); // debug
-        return cs->selectorText();
-    }
+    // FIXME: Handle all the selectors in the chain for comma-separated selectors.
+    if (m_selector)
+        return m_selector->selectorText();
     return DOMString();
 }
 
@@ -349,15 +346,6 @@ void CSSStyleRuleImpl::setDeclaration( C
     }
 }
 
-void CSSStyleRuleImpl::setNonCSSHints()
-{
-    CSSSelector *s = m_selector->first();
-    while ( s ) {
-	s->nonCSSHint = true;
-	s = m_selector->next();
-    }
-}
-
 void CSSRuleListImpl::deleteRule ( unsigned long index )
 {
     CSSRuleImpl *rule = m_lstCSSRules.take( index );
@@ -384,4 +372,3 @@ unsigned long CSSRuleListImpl::insertRul
     // ### Should throw INDEX_SIZE_ERR exception instead! (TODO)
     return 0;
 }
-
Index: khtml/css/css_ruleimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_ruleimpl.h,v
retrieving revision 1.9
diff -u -p -r1.9 khtml/css/css_ruleimpl.h
--- khtml/css/css_ruleimpl.h	2003/08/29 22:04:02	1.9
+++ khtml/css/css_ruleimpl.h	2004/02/05 01:40:11
@@ -30,6 +30,7 @@
 #include "css/css_base.h"
 #include "misc/loader_client.h"
 #include "misc/shared.h"
+#include "css_valueimpl.h"
 
 namespace khtml {
     class CachedCSSStyleSheet;
@@ -191,6 +192,7 @@ protected:
     CSSStyleDeclarationImpl *m_style;
 };
 
+class CSSImportantRuleImpl;
 
 class CSSStyleRuleImpl : public CSSRuleImpl
 {
@@ -208,19 +210,16 @@ public:
 
     virtual bool parseString( const DOMString &string, bool = false );
 
-    void setSelector( QPtrList<CSSSelector> *selector) { m_selector = selector; }
+    void setSelector(CSSSelector* selector) { m_selector = selector; }
     void setDeclaration( CSSStyleDeclarationImpl *style);
 
-    QPtrList<CSSSelector> *selector() { return m_selector; }
+    CSSSelector* selector() { return m_selector; }
     CSSStyleDeclarationImpl *declaration() { return m_style; }
-
-    void setNonCSSHints();
-
+ 
 protected:
     CSSStyleDeclarationImpl *m_style;
-    QPtrList<CSSSelector> *m_selector;
+    CSSSelector* m_selector;
 };
-
 
 class CSSUnknownRuleImpl : public CSSRuleImpl
 {
Index: khtml/css/css_stylesheetimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_stylesheetimpl.cpp,v
retrieving revision 1.8
diff -u -p -r1.8 khtml/css/css_stylesheetimpl.cpp
--- khtml/css/css_stylesheetimpl.cpp	2004/01/26 22:33:18	1.8
+++ khtml/css/css_stylesheetimpl.cpp	2004/02/05 01:40:11
@@ -276,17 +276,6 @@ void CSSStyleSheetImpl::checkLoaded()
     if(m_parentNode) m_parentNode->sheetLoaded();
 }
 
-void CSSStyleSheetImpl::setNonCSSHints()
-{
-    StyleBaseImpl *rule = m_lstChildren->first();
-    while(rule) {
-        if(rule->isStyleRule()) {
-            static_cast<CSSStyleRuleImpl *>(rule)->setNonCSSHints();
-        }
-        rule = m_lstChildren->next();
-    }
-}
-
 khtml::DocLoader *CSSStyleSheetImpl::docLoader()
 {
     if ( !m_doc ) // doc is 0 for the user- and default-sheet!
Index: khtml/css/css_stylesheetimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_stylesheetimpl.h,v
retrieving revision 1.7
diff -u -p -r1.7 khtml/css/css_stylesheetimpl.h
--- khtml/css/css_stylesheetimpl.h	2004/01/26 22:33:18	1.7
+++ khtml/css/css_stylesheetimpl.h	2004/02/05 01:40:11
@@ -106,7 +106,6 @@ public:
     virtual bool parseString( const DOMString &string, bool strict = true );
 
     bool isLoading();
-    void setNonCSSHints();
 
     virtual void checkLoaded();
     khtml::DocLoader *docLoader();
Index: khtml/css/css_valueimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_valueimpl.cpp,v
retrieving revision 1.31
diff -u -p -r1.31 khtml/css/css_valueimpl.cpp
--- khtml/css/css_valueimpl.cpp	2004/01/30 07:44:44	1.31
+++ khtml/css/css_valueimpl.cpp	2004/02/05 01:40:11
@@ -227,12 +227,12 @@ DOMString CSSStyleDeclarationImpl::getSh
     QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
     CSSProperty *current;
     for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt )
-        if (current->m_id == propertyID && !current->nonCSSHint)
+        if (current->m_id == propertyID)
             return current->value();
     return 0;
 }
 
-DOMString CSSStyleDeclarationImpl::removeProperty( int propertyID, bool NonCSSHint )
+DOMString CSSStyleDeclarationImpl::removeProperty(int propertyID, bool notifyChanged)
 {
     if(!m_lstValues) return DOMString();
     DOMString value;
@@ -240,10 +240,11 @@ DOMString CSSStyleDeclarationImpl::remov
     QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
      CSSProperty *current;
      for ( lstValuesIt.toLast(); (current = lstValuesIt.current()); --lstValuesIt )
-         if (current->m_id == propertyID && NonCSSHint == current->nonCSSHint) {
+         if (current->m_id == propertyID) {
              value = current->value()->cssText();
              m_lstValues->removeRef(current);
-             setChanged();
+             if (notifyChanged)
+                 setChanged();
 	     break;
         }
 
@@ -278,56 +279,57 @@ bool CSSStyleDeclarationImpl::getPropert
     return false;
 }
 
-bool CSSStyleDeclarationImpl::setProperty(int id, const DOMString &value, bool important, bool nonCSSHint)
+bool CSSStyleDeclarationImpl::setProperty(int id, const DOMString &value, bool important, bool notifyChanged)
 {
     if(!m_lstValues) {
 	m_lstValues = new QPtrList<CSSProperty>;
 	m_lstValues->setAutoDelete(true);
     }
-    removeProperty(id, nonCSSHint );
+    removeProperty(id);
 
     CSSParser parser( strictParsing );
-    bool success = parser.parseValue( this, id, value, important, nonCSSHint );
+    bool success = parser.parseValue(this, id, value, important);
     if(!success)
 	kdDebug( 6080 ) << "CSSStyleDeclarationImpl::setProperty invalid property: [" << getPropertyName(id).string()
 			<< "] value: [" << value.string() << "]"<< endl;
-    else
+    else if (notifyChanged)
         setChanged();
     return success;
 }
 
-void CSSStyleDeclarationImpl::setProperty(int id, int value, bool important, bool nonCSSHint)
+void CSSStyleDeclarationImpl::setProperty(int id, int value, bool important, bool notifyChanged)
 {
     if(!m_lstValues) {
 	m_lstValues = new QPtrList<CSSProperty>;
 	m_lstValues->setAutoDelete(true);
     }
-    removeProperty(id, nonCSSHint );
+    removeProperty(id);
 
     CSSValueImpl * cssValue = new CSSPrimitiveValueImpl(value);
-    setParsedValue(id, cssValue, important, nonCSSHint, m_lstValues);
-    setChanged();
+    setParsedValue(id, cssValue, important, m_lstValues);
+    if (notifyChanged)
+        setChanged();
 }
 
-void CSSStyleDeclarationImpl::setStringProperty(int propertyId, const DOMString &value, CSSPrimitiveValue::UnitTypes type, bool important, bool nonCSSHint)
+void CSSStyleDeclarationImpl::setStringProperty(int propertyId, const DOMString &value, CSSPrimitiveValue::UnitTypes type, bool important)
 {
     if (!m_lstValues) {
 	m_lstValues = new QPtrList<CSSProperty>;
 	m_lstValues->setAutoDelete(true);
     }
-    removeProperty(propertyId, nonCSSHint);
-    setParsedValue(propertyId, new CSSPrimitiveValueImpl(value, type), important, nonCSSHint, m_lstValues);
+    removeProperty(propertyId);
+    setParsedValue(propertyId, new CSSPrimitiveValueImpl(value, type), important, m_lstValues);
     setChanged();
 }
 
-void CSSStyleDeclarationImpl::setImageProperty(int propertyId, const DOMString &URL, bool important, bool nonCSSHint)
+void CSSStyleDeclarationImpl::setImageProperty(int propertyId, const DOMString &URL, bool important)
 {
     if (!m_lstValues) {
 	m_lstValues = new QPtrList<CSSProperty>;
 	m_lstValues->setAutoDelete(true);
     }
-    removeProperty(propertyId, nonCSSHint);
-    setParsedValue(propertyId, new CSSImageValueImpl(URL, this), important, nonCSSHint, m_lstValues);
+    removeProperty(propertyId);
+    setParsedValue(propertyId, new CSSImageValueImpl(URL, this), important, m_lstValues);
     setChanged();
 }
 
@@ -338,17 +340,17 @@ void CSSStyleDeclarationImpl::setPropert
 	m_lstValues->setAutoDelete( true );
     }
 
-    CSSParser parser( strictParsing );
-    parser.parseDeclaration( this, propertyString, false );
+    CSSParser parser(strictParsing);
+    parser.parseDeclaration(this, propertyString);
     setChanged();
 }
 
-void CSSStyleDeclarationImpl::setLengthProperty(int id, const DOM::DOMString &value, bool important, bool nonCSSHint, bool _multiLength )
+void CSSStyleDeclarationImpl::setLengthProperty(int id, const DOM::DOMString &value, bool important, bool _multiLength )
 {
     bool parseMode = strictParsing;
     strictParsing = false;
     multiLength = _multiLength;
-    setProperty( id, value, important, nonCSSHint);
+    setProperty( id, value, important);
     strictParsing = parseMode;
     multiLength = false;
 }
@@ -378,40 +380,24 @@ DOM::DOMString CSSStyleDeclarationImpl::
     if ( m_lstValues) {
 	QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
 	CSSProperty *current;
-	for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) {
-	    if (!current->nonCSSHint) {
-		result += current->cssText();
-	    }
-	}
+	for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt )
+	    result += current->cssText();
     }
 
     return result;
 }
 
-void CSSStyleDeclarationImpl::setCssText(DOM::DOMString text)
+void CSSStyleDeclarationImpl::setCssText(const DOM::DOMString& text)
 {
-    if (m_lstValues) {
-	QPtrList<CSSProperty> nonCSSHints;
-
-	{
-	    // make sure to destruct iterator before reassigning list contents
-	    QPtrListIterator<CSSProperty> lstValuesIt(*m_lstValues);
-	    CSSProperty *current;
-	    for ( lstValuesIt.toFirst(); (current = lstValuesIt.current()); ++lstValuesIt ) {
-		if (current->nonCSSHint) {
-		    nonCSSHints.append(new CSSProperty(*current));
-		}
-	    }
-	}
-
-	*m_lstValues = nonCSSHints;
-    } else {
+    if (m_lstValues)
+        m_lstValues->clear();
+    else {
 	m_lstValues = new QPtrList<CSSProperty>;
-	m_lstValues->setAutoDelete( true );
+	m_lstValues->setAutoDelete(true);
     }
 
-    CSSParser parser( strictParsing );
-    parser.parseDeclaration( this, text, false );
+    CSSParser parser(strictParsing);
+    parser.parseDeclaration(this, text);
     setChanged();
 }
 
Index: khtml/css/css_valueimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/css_valueimpl.h,v
retrieving revision 1.22
diff -u -p -r1.22 khtml/css/css_valueimpl.h
--- khtml/css/css_valueimpl.h	2004/01/27 01:29:19	1.22
+++ khtml/css/css_valueimpl.h	2004/02/05 01:40:11
@@ -56,21 +56,21 @@ public:
 
     unsigned long length() const;
     CSSRuleImpl *parentRule() const;
-    DOM::DOMString removeProperty( int propertyID, bool NonCSSHints = false );
-    bool setProperty ( int propertyId, const DOM::DOMString &value, bool important = false, bool nonCSSHint = false);
-    void setProperty ( int propertyId, int value, bool important = false, bool nonCSSHint = false);
+    DOM::DOMString removeProperty(int propertyID, bool notifyChanged = true);
+    bool setProperty(int propertyId, const DOM::DOMString &value, bool important = false, bool notifyChanged = true);
+    void setProperty(int propertyId, int value, bool important = false, bool notifyChanged = true);
     // this treats integers as pixels!
     // needed for conversion of html attributes
-    void setLengthProperty(int id, const DOM::DOMString &value, bool important, bool nonCSSHint = true, bool multiLength = false);
-    void setStringProperty(int propertyId, const DOM::DOMString &value, DOM::CSSPrimitiveValue::UnitTypes, bool important = false, bool nonCSSHint = false); // parsed string value
-    void setImageProperty(int propertyId, const DOM::DOMString &URL, bool important = false, bool nonCSSHint = false);
+    void setLengthProperty(int id, const DOM::DOMString &value, bool important,bool multiLength = false);
+    void setStringProperty(int propertyId, const DOM::DOMString &value, DOM::CSSPrimitiveValue::UnitTypes, bool important = false); // parsed string value
+    void setImageProperty(int propertyId, const DOM::DOMString &URL, bool important = false);
 
     // add a whole, unparsed property
     void setProperty ( const DOMString &propertyString);
     DOM::DOMString item ( unsigned long index );
 
     virtual DOM::DOMString cssText() const;
-    void setCssText(DOM::DOMString str);
+    void setCssText(const DOM::DOMString& str);
 
     virtual bool isStyleDeclaration() { return true; }
 
@@ -82,6 +82,7 @@ public:
 
     QPtrList<CSSProperty> *values() { return m_lstValues; }
     void setNode(NodeImpl *_node) { m_node = _node; }
+    NodeImpl* node() { return m_node; }
 
     void setChanged();
 
@@ -360,14 +361,12 @@ public:
     {
 	m_id = -1;
 	m_bImportant = false;
-	nonCSSHint = false;
-        m_value = 0;
+	m_value = 0;
     }
     CSSProperty(const CSSProperty& o)
     {
         m_id = o.m_id;
         m_bImportant = o.m_bImportant;
-        nonCSSHint = o.nonCSSHint;
         m_value = o.m_value;
         if (m_value) m_value->ref();
     }
@@ -383,14 +382,16 @@ public:
 	}
     }
 
+    int id() const { return m_id; }
+    bool isImportant() const { return m_bImportant; }
+    
     CSSValueImpl *value() { return m_value; }
-
+    
     DOM::DOMString cssText() const;
 
     // make sure the following fits in 4 bytes.
-    int  m_id 		: 29;
+    int  m_id 		: 30;
     bool m_bImportant 	: 1;
-    bool nonCSSHint 	: 1;
 protected:
     CSSValueImpl *m_value;
 };
Index: khtml/css/cssparser.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssparser.cpp,v
retrieving revision 1.61
diff -u -p -r1.61 khtml/css/cssparser.cpp
--- khtml/css/cssparser.cpp	2004/01/30 07:44:44	1.61
+++ khtml/css/cssparser.cpp	2004/02/05 01:40:11
@@ -99,7 +99,6 @@ CSSParser::CSSParser( bool strictParsing
     rule = 0;
     id = 0;
     important = false;
-    nonCSSHint = false;
     inParseShortHand = false;
     
     defaultNamespace = anyNamespace;
@@ -131,7 +130,7 @@ CSSParser::~CSSParser()
 void ParseString::lower()
 {
     for (int i = 0; i < length; i++)
-        string[i] = QChar(string[i]).lower();
+        string[i] = QChar(string[i]).lower().unicode();
 }
 
 void CSSParser::parseSheet( CSSStyleSheetImpl *sheet, const DOMString &string )
@@ -197,11 +196,11 @@ CSSRuleImpl *CSSParser::parseRule( DOM::
 }
 
 bool CSSParser::parseValue( DOM::CSSStyleDeclarationImpl *declaration, int _id, const DOM::DOMString &string,
-			    bool _important, bool _nonCSSHint )
+			    bool _important)
 {
 #ifdef CSS_DEBUG
     kdDebug( 6080 ) << "CSSParser::parseValue: id=" << _id << " important=" << _important
-		    << " nonCSSHint=" << _nonCSSHint << " value='" << string.string() << "'" << endl;
+		    << " value='" << string.string() << "'" << endl;
 #endif
 
     styleElement = declaration->stylesheet();
@@ -224,8 +223,7 @@ bool CSSParser::parseValue( DOM::CSSStyl
 
     id = _id;
     important = _important;
-    nonCSSHint = _nonCSSHint;
-
+    
     CSSParser *old = currentParser;
     currentParser = this;
     cssyyparse( this );
@@ -238,7 +236,7 @@ bool CSSParser::parseValue( DOM::CSSStyl
     if ( numParsedProperties ) {
 	ok = true;
 	for ( int i = 0; i < numParsedProperties; i++ ) {
-	    declaration->removeProperty(parsedProperties[i]->m_id, nonCSSHint);
+	    declaration->removeProperty(parsedProperties[i]->m_id);
 	    declaration->values()->append( parsedProperties[i] );
 	}
 	numParsedProperties = 0;
@@ -247,12 +245,10 @@ bool CSSParser::parseValue( DOM::CSSStyl
     return ok;
 }
 
-bool CSSParser::parseDeclaration( DOM::CSSStyleDeclarationImpl *declaration, const DOM::DOMString &string,
-				  bool _nonCSSHint )
+bool CSSParser::parseDeclaration( DOM::CSSStyleDeclarationImpl *declaration, const DOM::DOMString &string )
 {
 #ifdef CSS_DEBUG
-    kdDebug( 6080 ) << "CSSParser::parseDeclaration: nonCSSHint=" << nonCSSHint
-		    << " value='" << string.string() << "'" << endl;
+    kdDebug( 6080 ) << "CSSParser::parseDeclaration:value='" << string.string() << "'" << endl;
 #endif
 
     styleElement = declaration->stylesheet();
@@ -273,8 +269,6 @@ bool CSSParser::parseDeclaration( DOM::C
     yytext = yy_c_buf_p = data;
     yy_hold_char = *yy_c_buf_p;
 
-    nonCSSHint = _nonCSSHint;
-
     CSSParser *old = currentParser;
     currentParser = this;
     cssyyparse( this );
@@ -287,7 +281,7 @@ bool CSSParser::parseDeclaration( DOM::C
     if ( numParsedProperties ) {
 	ok = true;
 	for ( int i = 0; i < numParsedProperties; i++ ) {
-	    declaration->removeProperty(parsedProperties[i]->m_id, false);
+	    declaration->removeProperty(parsedProperties[i]->m_id);
 	    declaration->values()->append( parsedProperties[i] );
 	}
 	numParsedProperties = 0;
@@ -302,7 +296,6 @@ void CSSParser::addProperty( int propId,
     prop->m_id = propId;
     prop->setValue( value );
     prop->m_bImportant = important;
-    prop->nonCSSHint = nonCSSHint;
 
     if ( numParsedProperties >= maxParsedProperties ) {
 	maxParsedProperties += 32;
@@ -706,7 +699,7 @@ bool CSSParser::parseValue( int propId, 
 
     case CSS_PROP_BACKGROUND_POSITION_X:
     case CSS_PROP_BACKGROUND_POSITION_Y:
-	valid_primitive = validUnit( value, FPercent|FLength, strict&(!nonCSSHint) );
+	valid_primitive = validUnit( value, FPercent|FLength, strict );
 	break;
 
     case CSS_PROP_BORDER_SPACING: {
@@ -728,7 +721,7 @@ bool CSSParser::parseValue( int propId, 
     }
     case CSS_PROP__KHTML_BORDER_HORIZONTAL_SPACING:
     case CSS_PROP__KHTML_BORDER_VERTICAL_SPACING:
-        valid_primitive = validUnit(value, FLength|FNonNeg, strict&(!nonCSSHint));
+        valid_primitive = validUnit(value, FLength|FNonNeg, strict);
         break;
     case CSS_PROP_SCROLLBAR_FACE_COLOR:         // IE5.5
     case CSS_PROP_SCROLLBAR_SHADOW_COLOR:       // IE5.5
@@ -758,7 +751,7 @@ bool CSSParser::parseValue( int propId, 
             valid_primitive = true; // Always allow this, even when strict parsing is on,
                                     // since we use this in our UA sheets.
 	else if ( id >= CSS_VAL_AQUA && id <= CSS_VAL_WINDOWTEXT || id == CSS_VAL_MENU ||
-	     (id >= CSS_VAL_GREY && id < CSS_VAL__KHTML_TEXT && (nonCSSHint|!strict)) ) {
+	     (id >= CSS_VAL_GREY && id < CSS_VAL__KHTML_TEXT && !strict) ) {
 	    valid_primitive = true;
 	} else {
 	    parsedValue = parseColor();
@@ -811,7 +804,7 @@ bool CSSParser::parseValue( int propId, 
 	if (id == CSS_VAL_THIN || id == CSS_VAL_MEDIUM || id == CSS_VAL_THICK)
 	    valid_primitive = true;
         else
-            valid_primitive = ( validUnit( value, FLength, strict&(!nonCSSHint) ) );
+            valid_primitive = ( validUnit( value, FLength, strict ) );
 	break;
 
     case CSS_PROP_LETTER_SPACING:       // normal | <length> | inherit
@@ -819,7 +812,7 @@ bool CSSParser::parseValue( int propId, 
 	if ( id == CSS_VAL_NORMAL )
 	    valid_primitive = true;
 	else
-            valid_primitive = validUnit( value, FLength, strict&(!nonCSSHint) );
+            valid_primitive = validUnit( value, FLength, strict );
 	break;
 
     case CSS_PROP_TEXT_INDENT:          // <length> | <percentage> | inherit
@@ -827,7 +820,7 @@ bool CSSParser::parseValue( int propId, 
     case CSS_PROP_PADDING_RIGHT:        //   Which is defined as
     case CSS_PROP_PADDING_BOTTOM:       //   <length> | <percentage>
     case CSS_PROP_PADDING_LEFT:         ////
-	valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+	valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict ) );
 	break;
 
     case CSS_PROP_MAX_HEIGHT:           // <length> | <percentage> | none | inherit
@@ -839,7 +832,7 @@ bool CSSParser::parseValue( int propId, 
 	/* nobreak */
     case CSS_PROP_MIN_HEIGHT:           // <length> | <percentage> | inherit
     case CSS_PROP_MIN_WIDTH:            // <length> | <percentage> | inherit
-    	valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
+    	valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict ) );
 	break;
 
     case CSS_PROP_FONT_SIZE:
@@ -847,7 +840,7 @@ bool CSSParser::parseValue( int propId, 
 	if (id >= CSS_VAL_XX_SMALL && id <= CSS_VAL_LARGER)
 	    valid_primitive = true;
 	else
-	    valid_primitive = ( validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+	    valid_primitive = ( validUnit( value, FLength|FPercent, strict ) );
 	break;
 
     case CSS_PROP_FONT_STYLE:           // normal | italic | oblique | inherit
@@ -867,7 +860,7 @@ bool CSSParser::parseValue( int propId, 
 	if ( id >= CSS_VAL_BASELINE && id <= CSS_VAL__KHTML_BASELINE_MIDDLE )
 	    valid_primitive = true;
 	else
-	    valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+	    valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict ) );
 	break;
 
     case CSS_PROP_HEIGHT:               // <length> | <percentage> | auto | inherit
@@ -876,7 +869,7 @@ bool CSSParser::parseValue( int propId, 
 	    valid_primitive = true;
 	else
 	    // ### handle multilength case where we allow relative units
-	    valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict&(!nonCSSHint) ) );
+	    valid_primitive = ( !id && validUnit( value, FLength|FPercent|FNonNeg, strict ) );
 	break;
 
     case CSS_PROP_BOTTOM:               // <length> | <percentage> | auto | inherit
@@ -890,7 +883,7 @@ bool CSSParser::parseValue( int propId, 
 	if ( id == CSS_VAL_AUTO )
 	    valid_primitive = true;
 	else
-	    valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict&(!nonCSSHint) ) );
+	    valid_primitive = ( !id && validUnit( value, FLength|FPercent, strict ) );
 	break;
 
     case CSS_PROP_Z_INDEX:              // auto | <integer> | inherit
@@ -910,7 +903,7 @@ bool CSSParser::parseValue( int propId, 
 	if ( id == CSS_VAL_NORMAL )
 	    valid_primitive = true;
 	else
-	    valid_primitive = ( !id && validUnit( value, FNumber|FLength|FPercent, strict&(!nonCSSHint) ) );
+	    valid_primitive = ( !id && validUnit( value, FNumber|FLength|FPercent, strict ) );
 	break;
 #if 0
 	// removed from CSS 2.1
@@ -1021,7 +1014,7 @@ bool CSSParser::parseValue( int propId, 
 #endif
         break;
     case CSS_PROP_OUTLINE_OFFSET:
-        valid_primitive = validUnit(value, FLength, strict&(!nonCSSHint));
+        valid_primitive = validUnit(value, FLength, strict);
         break;
     case CSS_PROP_TEXT_SHADOW: // CSS2 property, dropped in CSS2.1, back in CSS3, so treat as CSS3
         if (id == CSS_VAL_NONE)
@@ -1078,7 +1071,7 @@ bool CSSParser::parseValue( int propId, 
         if (id == CSS_VAL_SMALL || id == CSS_VAL_LARGE || id == CSS_VAL_MEDIUM)
             valid_primitive = true;
         else
-            valid_primitive = validUnit(value, FLength|FPercent, strict&(!nonCSSHint));
+            valid_primitive = validUnit(value, FLength|FPercent, strict);
         break;
     case CSS_PROP__KHTML_MARQUEE_STYLE:
         if (id == CSS_VAL_NONE || id == CSS_VAL_SLIDE || id == CSS_VAL_SCROLL || id == CSS_VAL_ALTERNATE ||
@@ -1089,13 +1082,13 @@ bool CSSParser::parseValue( int propId, 
         if (id == CSS_VAL_INFINITE)
             valid_primitive = true;
         else
-            valid_primitive = validUnit(value, FInteger|FNonNeg, strict&(!nonCSSHint));
+            valid_primitive = validUnit(value, FInteger|FNonNeg, strict);
         break;
     case CSS_PROP__KHTML_MARQUEE_SPEED:
         if (id == CSS_VAL_NORMAL || id == CSS_VAL_SLOW || id == CSS_VAL_FAST)
             valid_primitive = true;
         else
-            valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict&(!nonCSSHint));
+            valid_primitive = validUnit(value, FTime|FInteger|FNonNeg, strict);
         break;
     case CSS_PROP__KHTML_USER_MODIFY:	// read-only | read-write
         if (id == CSS_VAL_READ_ONLY || id == CSS_VAL_READ_WRITE)
@@ -1888,7 +1881,7 @@ bool CSSParser::parseShadow( int propId,
             // The only other type of value that's ok is a color value.
             CSSPrimitiveValueImpl* parsedColor = 0;
             bool isColor = (val->id >= CSS_VAL_AQUA && val->id <= CSS_VAL_WINDOWTEXT || val->id == CSS_VAL_MENU ||
-                            (val->id >= CSS_VAL_GREY && val->id <= CSS_VAL__KHTML_TEXT && (nonCSSHint|!strict)));
+                            (val->id >= CSS_VAL_GREY && val->id <= CSS_VAL__KHTML_TEXT && !strict));
             if (isColor) {
                 if (!context.allowColor)
                     return context.failed();
Index: khtml/css/cssparser.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssparser.h,v
retrieving revision 1.21
diff -u -p -r1.21 khtml/css/cssparser.h
--- khtml/css/cssparser.h	2004/01/30 07:44:44	1.21
+++ khtml/css/cssparser.h	2004/02/05 01:40:11
@@ -108,9 +108,8 @@ namespace DOM {
 	void parseSheet( DOM::CSSStyleSheetImpl *sheet, const DOM::DOMString &string );
 	DOM::CSSRuleImpl *parseRule( DOM::CSSStyleSheetImpl *sheet, const DOM::DOMString &string );
 	bool parseValue( DOM::CSSStyleDeclarationImpl *decls, int id, const DOM::DOMString &string,
-			 bool _important, bool _nonCSSHint );
-	bool parseDeclaration( DOM::CSSStyleDeclarationImpl *decls, const DOM::DOMString &string,
-			       bool _nonCSSHint );
+			 bool _important );
+	bool parseDeclaration( DOM::CSSStyleDeclarationImpl *decls, const DOM::DOMString &string );
 
 	static CSSParser *current() { return currentParser; }
 
@@ -139,7 +138,6 @@ namespace DOM {
     public:
 	bool strict;
 	bool important;
-	bool nonCSSHint;
 	int id;
 	DOM::StyleListImpl *styleElement;
 	DOM::CSSRuleImpl *rule;
Index: khtml/css/cssstyleselector.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssstyleselector.cpp,v
retrieving revision 1.124
diff -u -p -r1.124 khtml/css/cssstyleselector.cpp
--- khtml/css/cssstyleselector.cpp	2004/01/30 07:44:44	1.124
+++ khtml/css/cssstyleselector.cpp	2004/02/05 01:40:11
@@ -107,16 +107,16 @@ if (id == propID) \
 
 namespace khtml {
 
-CSSStyleSelectorList *CSSStyleSelector::defaultStyle = 0;
-CSSStyleSelectorList *CSSStyleSelector::defaultQuirksStyle = 0;
-CSSStyleSelectorList *CSSStyleSelector::defaultPrintStyle = 0;
+CSSRuleSet *CSSStyleSelector::defaultStyle = 0;
+CSSRuleSet *CSSStyleSelector::defaultQuirksStyle = 0;
+CSSRuleSet *CSSStyleSelector::defaultPrintStyle = 0;
 CSSStyleSheetImpl *CSSStyleSelector::defaultSheet = 0;
 RenderStyle* CSSStyleSelector::styleNotYetAvailable = 0;
 CSSStyleSheetImpl *CSSStyleSelector::quirksSheet = 0;
 
 static CSSStyleSelector::Encodedurl *encodedurl = 0;
 
-enum PseudoState { PseudoUnknown, PseudoNone, PseudoLink, PseudoVisited};
+enum PseudoState { PseudoUnknown, PseudoNone, PseudoAnyLink, PseudoLink, PseudoVisited};
 static PseudoState pseudoState;
 
 
@@ -131,34 +131,27 @@ CSSStyleSelector::CSSStyleSelector( Docu
     if(!defaultStyle) loadDefaultStyle(settings);
     m_medium = view ? view->mediaType() : QString("all");
 
-    selectors = 0;
-    selectorCache = 0;
-    properties = 0;
-    userStyle = 0;
-    userSheet = 0;
+    m_userStyle = 0;
+    m_userSheet = 0;
     paintDeviceMetrics = doc->paintDeviceMetrics();
 
+    // FIXME: This sucks! The user sheet is reparsed every time!
     if ( !userStyleSheet.isEmpty() ) {
-        userSheet = new DOM::CSSStyleSheetImpl(doc);
-        userSheet->parseString( DOMString( userStyleSheet ) );
+        m_userSheet = new DOM::CSSStyleSheetImpl(doc);
+        m_userSheet->parseString( DOMString( userStyleSheet ) );
 
-        userStyle = new CSSStyleSelectorList();
-        userStyle->append( userSheet, m_medium );
+        m_userStyle = new CSSRuleSet();
+        m_userStyle->addRulesFromSheet( m_userSheet, m_medium );
     }
 
     // add stylesheets from document
-    authorStyle = new CSSStyleSelectorList();
+    m_authorStyle = new CSSRuleSet();
 
+    QPtrListIterator<StyleSheetImpl> it(styleSheets->styleSheets);
+    for (; it.current(); ++it)
+        if (it.current()->isCSSStyleSheet())
+            m_authorStyle->addRulesFromSheet(static_cast<CSSStyleSheetImpl*>(it.current()), m_medium);
 
-    QPtrListIterator<StyleSheetImpl> it( styleSheets->styleSheets );
-    for ( ; it.current(); ++it ) {
-        if ( it.current()->isCSSStyleSheet() ) {
-            authorStyle->append( static_cast<CSSStyleSheetImpl*>( it.current() ), m_medium );
-        }
-    }
-
-    buildLists();
-
     //kdDebug( 6080 ) << "number of style sheets in document " << authorStyleSheets.count() << endl;
     //kdDebug( 6080 ) << "CSSStyleSelector: author style has " << authorStyle->count() << " elements"<< endl;
 
@@ -187,8 +180,8 @@ CSSStyleSelector::CSSStyleSelector( CSSS
     KHTMLView *view = sheet->doc()->view();
     m_medium =  view ? view->mediaType() : QString("all");
 
-    authorStyle = new CSSStyleSelectorList();
-    authorStyle->append( sheet, m_medium );
+    m_authorStyle = new CSSRuleSet();
+    m_authorStyle->addRulesFromSheet( sheet, m_medium );
 }
 
 void CSSStyleSelector::init()
@@ -196,29 +189,16 @@ void CSSStyleSelector::init()
     element = 0;
     settings = 0;
     paintDeviceMetrics = 0;
-    propsToApply = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *));
-    pseudoProps = (CSSOrderedProperty **)malloc(128*sizeof(CSSOrderedProperty *));
-    propsToApplySize = 128;
-    pseudoPropsSize = 128;
+    m_matchedRuleCount = m_matchedDeclCount = m_tmpRuleCount = 0;
 }
 
 CSSStyleSelector::~CSSStyleSelector()
 {
-    clearLists();
-    delete authorStyle;
-    delete userStyle;
-    delete userSheet;
-    free(propsToApply);
-    free(pseudoProps);
+    delete m_authorStyle;
+    delete m_userStyle;
+    delete m_userSheet;
 }
 
-void CSSStyleSelector::addSheet( CSSStyleSheetImpl *sheet )
-{
-    KHTMLView *view = sheet->doc()->view();
-    m_medium = view ? view->mediaType() : QString("all");
-    authorStyle->append( sheet, m_medium );
-}
-
 void CSSStyleSelector::loadDefaultStyle(const KHTMLSettings *s)
 {
     if(defaultStyle) return;
@@ -242,11 +222,11 @@ void CSSStyleSelector::loadDefaultStyle(
         defaultSheet->parseString( str );
 
         // Collect only strict-mode rules.
-        defaultStyle = new CSSStyleSelectorList();
-        defaultStyle->append( defaultSheet, "screen" );
-
-        defaultPrintStyle = new CSSStyleSelectorList();
-        defaultPrintStyle->append( defaultSheet, "print" );
+        defaultStyle = new CSSRuleSet();
+        defaultStyle->addRulesFromSheet( defaultSheet, "screen" );
+        
+        defaultPrintStyle = new CSSRuleSet();
+        defaultPrintStyle->addRulesFromSheet( defaultSheet, "print" );
     }
     {
         QFile f(locate( "data", "khtml/css/quirks.css" ) );
@@ -265,8 +245,8 @@ void CSSStyleSelector::loadDefaultStyle(
         quirksSheet->parseString( str );
 
         // Collect only quirks-mode rules.
-        defaultQuirksStyle = new CSSStyleSelectorList();
-        defaultQuirksStyle->append( quirksSheet, "screen" );
+        defaultQuirksStyle = new CSSRuleSet();
+        defaultQuirksStyle->addRulesFromSheet( quirksSheet, "screen" );
     }
 
     //kdDebug() << "CSSStyleSelector: default style has " << defaultStyle->count() << " elements"<< endl;
@@ -286,32 +266,165 @@ void CSSStyleSelector::clear()
     styleNotYetAvailable = 0;
 }
 
-static inline void bubbleSort( CSSOrderedProperty **b, CSSOrderedProperty **e )
+void CSSStyleSelector::addMatchedRule(CSSRuleData* rule)
 {
-    while( b < e ) {
-	bool swapped = FALSE;
-        CSSOrderedProperty **y = e+1;
-	CSSOrderedProperty **x = e;
-        CSSOrderedProperty **swappedPos = 0;
-	do {
-	    if ( !((**(--x)) < (**(--y))) ) {
-		swapped = TRUE;
-                swappedPos = x;
-                CSSOrderedProperty *tmp = *y;
-                *y = *x;
-                *x = tmp;
-	    }
-	} while( x != b );
-	if ( !swapped ) break;
-        b = swappedPos + 1;
+    if (m_matchedRules.size() <= m_matchedRuleCount)
+        m_matchedRules.resize(2*m_matchedRules.size()+1);
+    m_matchedRules[m_matchedRuleCount++] = rule;
+}
+
+void CSSStyleSelector::addMatchedDeclaration(CSSStyleDeclarationImpl* decl)
+{
+    if (m_matchedDecls.size() <= m_matchedDeclCount)
+        m_matchedDecls.resize(2*m_matchedDecls.size()+1);
+    m_matchedDecls[m_matchedDeclCount++] = decl;
+}
+
+void CSSStyleSelector::matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex)
+{
+    m_matchedRuleCount = 0;
+    firstRuleIndex = lastRuleIndex = -1;
+    if (!rules || !element) return;
+    
+    // We need to collect the rules for id, class, tag, and everything else into a buffer and
+    // then sort the buffer.
+    if (element->hasID())
+        matchRulesForList(rules->getIDRules(element->getIDAttribute().implementation()),
+                          firstRuleIndex, lastRuleIndex);
+    if (element->hasClass()) {
+        for (const AtomicStringList* singleClass = element->getClassList();
+             singleClass; singleClass = singleClass->next())
+            matchRulesForList(rules->getClassRules(singleClass->string().implementation()),
+                                                   firstRuleIndex, lastRuleIndex);
     }
+    matchRulesForList(rules->getTagRules((void*)(int)localNamePart(element->id())),
+                      firstRuleIndex, lastRuleIndex);
+    matchRulesForList(rules->getUniversalRules(), firstRuleIndex, lastRuleIndex);
+    
+    // If we didn't match any rules, we're done.
+    if (m_matchedRuleCount == 0) return;
+    
+    // Sort the set of matched rules.
+    sortMatchedRules(0, m_matchedRuleCount);
+    
+    // Now transfer the set of matched rules over to our list of decls.
+    for (unsigned i = 0; i < m_matchedRuleCount; i++)
+        addMatchedDeclaration(m_matchedRules[i]->rule()->declaration());
 }
 
+void CSSStyleSelector::matchRulesForList(CSSRuleDataList* rules,
+                                         int& firstRuleIndex, int& lastRuleIndex)
+{
+    if (!rules) return;
+    for (CSSRuleData* d = rules->first(); d; d = d->next()) {
+        CSSStyleRuleImpl* rule = d->rule();
+        Q_UINT16 cssTagId = localNamePart(element->id());
+        Q_UINT16 tag = localNamePart(d->selector()->tag);
+        if ((cssTagId == tag || tag == anyLocalName) && checkSelector(d->selector(), element)) {
+            // If the rule has no properties to apply, then ignore it.
+            CSSStyleDeclarationImpl* decl = rule->declaration();
+            if (!decl) continue;
+            
+            // If we're matching normal rules, set a pseudo bit if 
+            // we really just matched a pseudo-element.
+            if (dynamicPseudo != RenderStyle::NOPSEUDO && pseudoStyle == RenderStyle::NOPSEUDO)
+                style->setHasPseudoStyle(dynamicPseudo);
+            else  {
+                // Update our first/last rule indices in the matched rules array.
+                lastRuleIndex = m_matchedDeclCount + m_matchedRuleCount;
+                if (firstRuleIndex == -1) firstRuleIndex = m_matchedDeclCount + m_matchedRuleCount;
+
+                // Add this rule to our list of matched rules.
+                addMatchedRule(d);
+            }
+        }
+    }
+}
+
+bool operator >(CSSRuleData& r1, CSSRuleData& r2)
+{
+    int spec1 = r1.selector()->specificity();
+    int spec2 = r2.selector()->specificity();
+    return (spec1 == spec2) ? r1.position() > r2.position() : spec1 > spec2; 
+}
+bool operator <=(CSSRuleData& r1, CSSRuleData& r2)
+{
+    return !(r1 > r2);
+}
+
+void CSSStyleSelector::sortMatchedRules(uint start, uint end)
+{
+    if (start >= end || (end-start == 1))
+        return; // Sanity check.
+    
+    if (end - start <= 6) {
+        // Apply a bubble sort for smaller lists.
+        for (uint i = end-1; i > start; i--) {
+            bool sorted = true;
+            for (uint j = start; j < i; j++) {
+                CSSRuleData* elt = m_matchedRules[j];
+                CSSRuleData* elt2 = m_matchedRules[j+1];
+                if (*elt > *elt2) {
+                    sorted = false;
+                    m_matchedRules[j] = elt2;
+                    m_matchedRules[j+1] = elt;
+                }
+            }
+            if (sorted)
+                return;
+        }
+    }
+    else {
+        // Peform a merge sort for larger lists.
+        uint mid = (start+end)/2;
+        sortMatchedRules(start, mid);
+        sortMatchedRules(mid, end);
+        
+        CSSRuleData* elt = m_matchedRules[mid-1];
+        CSSRuleData* elt2 = m_matchedRules[mid];
+        
+        // Handle the fast common case (of equal specificity).  The list may already
+        // be completely sorted.
+        if (*elt <= *elt2)
+            return;
+        
+        // We have to merge sort.  Ensure our merge buffer is big enough to hold
+        // all the items.
+        m_tmpRules.resize(end - start);
+        uint i1 = start;
+        uint i2 = mid;
+        
+        elt = m_matchedRules[i1];
+        elt2 = m_matchedRules[i2];
+        
+        while (i1 < mid || i2 < end) {
+            if (i1 < mid && (i2 == end || *elt <= *elt2)) {
+                m_tmpRules[m_tmpRuleCount++] = elt;
+                i1++;
+                if (i1 < mid)
+                    elt = m_matchedRules[i1];
+            }
+            else {
+                m_tmpRules[m_tmpRuleCount++] = elt2;
+                i2++;
+                if (i2 < end)
+                    elt2 = m_matchedRules[i2];
+            }
+        }
+        
+        for (uint i = start; i < end; i++)
+            m_matchedRules[i] = m_tmpRules[i-start];
+        
+        m_tmpRuleCount = 0;
+    }    
+}
+
 void CSSStyleSelector::initForStyleResolve(ElementImpl* e, RenderStyle* defaultParent)
 {
     // set some variables we will need
     ::encodedurl = &encodedurl;
     pseudoState = PseudoUnknown;
+    pseudoStyle = RenderStyle::NOPSEUDO;
     
     element = e;
     parentNode = e->parentNode();
@@ -326,6 +439,12 @@ void CSSStyleSelector::initForStyleResol
     paintDeviceMetrics = element->getDocument()->paintDeviceMetrics();
     
     style = 0;
+    
+    m_matchedRuleCount = 0;
+    m_matchedDeclCount = 0;
+    m_tmpRuleCount = 0;
+    
+    fontDirty = false;
 }
 
 RenderStyle* CSSStyleSelector::styleForElement(ElementImpl* e, RenderStyle* defaultParent)
@@ -347,86 +466,88 @@ RenderStyle* CSSStyleSelector::styleForE
     else
         parentStyle = style;
     
-    unsigned int numPropsToApply = 0;
-    
-    // try to sort out most style rules as early as possible.
-    Q_UINT16 cssTagId = localNamePart(e->id());
-    int smatch = 0;
-    int schecked = 0;
-
-    for ( unsigned int i = 0; i < selectors_size; i++ ) {
-	Q_UINT16 tag = localNamePart(selectors[i]->tag);
-	if ( cssTagId == tag || tag == anyLocalName ) {
-	    ++schecked;
-
-	    checkSelector( i, e );
-
-	    if ( selectorCache[i].state == Applies ) {
-		++smatch;
-
-		//qDebug("adding property" );
-		for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
-		    for ( unsigned int j = 0; j < (unsigned int )selectorCache[i].props[p+1]; ++j ) {
-                        if (numPropsToApply >= propsToApplySize ) {
-                            propsToApplySize *= 2;
-			    propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) );
-			}
-			propsToApply[numPropsToApply++] = properties[selectorCache[i].props[p]+j];
-		    }
-	    }
-            else if (selectorCache[i].state == AppliesPseudo)
-                style->setHasPseudoStyle((RenderStyle::PseudoId)selectors[i]->pseudoId);
-	}
-	else
-	    selectorCache[i].state = Invalid;
-
+    // 1. First we match rules from the user agent sheet.
+    int firstUARule = -1, lastUARule = -1;
+    matchRules(defaultStyle, firstUARule, lastUARule);
+    
+    // 2. In quirks mode, we match rules from the quirks user agent sheet.
+    if (!strictParsing)
+        matchRules(defaultQuirksStyle, firstUARule, lastUARule);
+    
+    // 3. If our medium is print, then we match rules from the print sheet.
+    if (m_medium == "print")
+        matchRules(defaultPrintStyle, firstUARule, lastUARule);
+    
+    // 4. Now we check user sheet rules.
+    int firstUserRule = -1, lastUserRule = -1;
+    matchRules(m_userStyle, firstUserRule, lastUserRule);
+    
+    // 5. Now check author rules, beginning first with presentational attributes
+    // mapped from HTML.
+    int firstAuthorRule = -1, lastAuthorRule = -1;
+    CSSStyleDeclarationImpl* attributeDecl = e->attributeStyleDecl();
+    if (attributeDecl) {
+        firstAuthorRule = lastAuthorRule = m_matchedDeclCount;
+        addMatchedDeclaration(attributeDecl);
+    }
+    
+    // Table cells share an additional mapped rule.
+    attributeDecl = e->additionalAttributeStyleDecl();
+    if (attributeDecl) {
+        if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
+        lastAuthorRule = m_matchedDeclCount;
+        addMatchedDeclaration(attributeDecl);
+    }
+    
+    // 6. Check the rules in author sheets next.
+    matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
+    
+    // 7. Now check our inline style attribute.
+    CSSStyleDeclarationImpl* inlineDecl = e->inlineStyleDecl();
+    if (inlineDecl) {
+        if (firstAuthorRule == -1) firstAuthorRule = m_matchedDeclCount;
+        lastAuthorRule = m_matchedDeclCount;
+        addMatchedDeclaration(inlineDecl);
+    }
+    
+    // Now we have all of the matched rules in the appropriate order.  Walk the rules and apply
+    // high-priority properties first, i.e., those properties that other properties depend on.
+    // The order is (1) high-priority not important, (2) high-priority important, (3) normal not important
+    // and (4) normal important.
+    applyDeclarations(true, false, 0, m_matchedDeclCount-1);
+    applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
+    applyDeclarations(true, true, firstUserRule, lastUserRule);
+    applyDeclarations(true, true, firstUARule, lastUARule);
+    
+    // If our font got dirtied, go ahead and update it now.
+    if (fontDirty) {
+        checkForGenericFamilyChange(style, parentStyle);
+        style->htmlFont().update(paintDeviceMetrics);
+        fontDirty = false;
     }
-
-    //qDebug( "styleForElement( %s )", e->tagName().string().latin1() );
-    //qDebug( "%d selectors, %d checked,  %d match,  %d properties ( of %d )",
-    //selectors_size, schecked, smatch, propsToApply->count(), properties_size );
-
-    // inline style declarations, after all others. non css hints
-    // count as author rules, and come before all other style sheets, see hack in append()
-    numPropsToApply = addInlineDeclarations( e, e->m_styleDecls, numPropsToApply );
-            
-    bubbleSort( propsToApply, propsToApply+numPropsToApply-1 );
     
-    //qDebug("applying properties, count=%d", propsToApply->count() );
-
-    // we can't apply style rules without a view() and a part. This
-    // tends to happen on delayed destruction of widget Renderobjects
-    if ( part ) {
+    // Now do the normal priority properties.
+    applyDeclarations(false, false, 0, m_matchedDeclCount-1);
+    applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
+    applyDeclarations(false, true, firstUserRule, lastUserRule);
+    applyDeclarations(false, true, firstUARule, lastUARule);
+    
+    // If our font got dirtied by one of the non-essential font props, 
+    // go ahead and update it a second time.
+    if (fontDirty) {
+        checkForGenericFamilyChange(style, parentStyle);
+        style->htmlFont().update(paintDeviceMetrics);
         fontDirty = false;
-
-        if (numPropsToApply ) {
-            CSSStyleSelector::style = style;
-            for (unsigned int i = 0; i < numPropsToApply; ++i) {
-		if ( fontDirty && propsToApply[i]->priority >= (1 << 30) ) {
-		    // we are past the font properties, time to update to the
-		    // correct font
-		    checkForGenericFamilyChange(style, parentStyle);
-		    CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
-		    fontDirty = false;
-		}
-                DOM::CSSProperty *prop = propsToApply[i]->prop;
-                applyRule( prop->m_id, prop->value() );
-	    }
-	    if ( fontDirty ) {
-	        checkForGenericFamilyChange(style, parentStyle);
-		CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
-	    }
-        }
-
-        // Clean up our style object's display and text decorations (among other fixups).
-        adjustRenderStyle(style, e);
     }
+    
+    // Clean up our style object's display and text decorations (among other fixups).
+    adjustRenderStyle(style, e);
 
     // Now return the style.
     return style;
 }
 
-RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudoStyle, 
+RenderStyle* CSSStyleSelector::pseudoStyleForElement(RenderStyle::PseudoId pseudo, 
                                                      ElementImpl* e, RenderStyle* parentStyle)
 {
     if (!e)
@@ -442,37 +563,18 @@ RenderStyle* CSSStyleSelector::pseudoSty
     }
     
     initForStyleResolve(e, parentStyle);
+    pseudoStyle = pseudo;
     
-    unsigned int numPseudoProps = 0;
+    // Since we don't use pseudo-elements in any of our quirk/print user agent rules, don't waste time walking
+    // those rules.
     
-    // try to sort out most style rules as early as possible.
-    Q_UINT16 cssTagId = localNamePart(e->id());
-    int schecked = 0;
-    
-    for ( unsigned int i = 0; i < selectors_size; i++ ) {
-        Q_UINT16 tag = localNamePart(selectors[i]->tag);
-        if ( cssTagId == tag || tag == anyLocalName ) {
-            ++schecked;
-            
-            checkSelector( i, e, pseudoStyle );
-            
-            if ( selectorCache[i].state == AppliesPseudo ) {
-                for ( unsigned int p = 0; p < selectorCache[i].props_size; p += 2 )
-                    for ( unsigned int j = 0; j < (unsigned int) selectorCache[i].props[p+1]; ++j ) {
-                        if (numPseudoProps >= pseudoPropsSize ) {
-                            pseudoPropsSize *= 2;
-                            pseudoProps = (CSSOrderedProperty **)realloc( pseudoProps, pseudoPropsSize*sizeof( CSSOrderedProperty * ) );
-                        }
-                        pseudoProps[numPseudoProps++] = properties[selectorCache[i].props[p]+j];
-                        properties[selectorCache[i].props[p]+j]->pseudoId = (RenderStyle::PseudoId) selectors[i]->pseudoId;
-                    }
-            }
-        }
-        else
-            selectorCache[i].state = Invalid;
-    }
+    // Check UA, user and author rules.
+    int firstUARule = -1, lastUARule = -1, firstUserRule = -1, lastUserRule = -1, firstAuthorRule = -1, lastAuthorRule = -1;
+    matchRules(defaultStyle, firstUARule, lastUARule);
+    matchRules(m_userStyle, firstUserRule, lastUserRule);
+    matchRules(m_authorStyle, firstAuthorRule, lastAuthorRule);
     
-    if (numPseudoProps == 0)
+    if (m_matchedDeclCount == 0)
         return 0;
     
     style = new RenderStyle();
@@ -481,38 +583,37 @@ RenderStyle* CSSStyleSelector::pseudoSty
     else
         parentStyle = style;
     style->noninherited_flags._styleType = pseudoStyle;
-        
-    bubbleSort( pseudoProps, pseudoProps+numPseudoProps-1 );
-        
-    // we can't apply style rules without a view() and a part. This
-    // tends to happen on delayed destruction of widget Renderobjects
-    if ( part ) {
+    
+    // High-priority properties.
+    applyDeclarations(true, false, 0, m_matchedDeclCount-1);
+    applyDeclarations(true, true, firstAuthorRule, lastAuthorRule);
+    applyDeclarations(true, true, firstUserRule, lastUserRule);
+    applyDeclarations(true, true, firstUARule, lastUARule);
+    
+    // If our font got dirtied, go ahead and update it now.
+    if (fontDirty) {
+        checkForGenericFamilyChange(style, parentStyle);
+        style->htmlFont().update(paintDeviceMetrics);
         fontDirty = false;
-        if ( numPseudoProps ) {
-            fontDirty = false;
-            //qDebug("%d applying %d pseudo props", e->cssTagId(), pseudoProps->count() );
-            for (unsigned int i = 0; i < numPseudoProps; ++i) {
-                if ( fontDirty && pseudoProps[i]->priority >= (1 << 30) ) {
-                    // we are past the font properties, time to update to the
-                    // correct font
-                    style->htmlFont().update( paintDeviceMetrics );
-                    fontDirty = false;
-                }
-                
-               DOM::CSSProperty *prop = pseudoProps[i]->prop;
-               applyRule( prop->m_id, prop->value() );
-            }
-            
-            if ( fontDirty ) {
-                checkForGenericFamilyChange(style, parentStyle);
-                style->htmlFont().update( paintDeviceMetrics );
-            }
-        }
     }
     
-    // Do the post-resolve fixups on the style.
+    // Now do the normal priority properties.
+    applyDeclarations(false, false, 0, m_matchedDeclCount-1);
+    applyDeclarations(false, true, firstAuthorRule, lastAuthorRule);
+    applyDeclarations(false, true, firstUserRule, lastUserRule);
+    applyDeclarations(false, true, firstUARule, lastUARule);
+    
+    // If our font got dirtied by one of the non-essential font props, 
+    // go ahead and update it a second time.
+    if (fontDirty) {
+        checkForGenericFamilyChange(style, parentStyle);
+        style->htmlFont().update(paintDeviceMetrics);
+        fontDirty = false;
+    }
+    
+    // Clean up our style object's display and text decorations (among other fixups).
     adjustRenderStyle(style, 0);
-        
+
     // Now return the style.
     return style;
 }
@@ -593,77 +694,6 @@ void CSSStyleSelector::adjustRenderStyle
         style->addToTextDecorationsInEffect(style->textDecoration());
 }
 
-unsigned int CSSStyleSelector::addInlineDeclarations(DOM::ElementImpl* e,
-                                                     DOM::CSSStyleDeclarationImpl *decl,
-                                                     unsigned int numProps)
-{
-    CSSStyleDeclarationImpl* addDecls = 0;
-    if (e->id() == ID_TD || e->id() == ID_TH)     // For now only TableCellElement implements the
-        addDecls = e->getAdditionalStyleDecls();  // virtual function for shared cell rules.
-
-    if (!decl && !addDecls)
-        return numProps;
-
-    QPtrList<CSSProperty>* values = decl ? decl->values() : 0;
-    QPtrList<CSSProperty>* addValues = addDecls ? addDecls->values() : 0;
-    if (!values && !addValues)
-        return numProps;
-    
-    int firstLen = values ? values->count() : 0;
-    int secondLen = addValues ? addValues->count() : 0;
-    int totalLen = firstLen + secondLen;
-
-    if (inlineProps.size() < (uint)totalLen)
-        inlineProps.resize(totalLen + 1);
-    
-    if (numProps + totalLen >= propsToApplySize ) {
-        propsToApplySize += propsToApplySize;
-        propsToApply = (CSSOrderedProperty **)realloc( propsToApply, propsToApplySize*sizeof( CSSOrderedProperty * ) );
-    }
-
-    CSSOrderedProperty *array = (CSSOrderedProperty *)inlineProps.data();
-    for(int i = 0; i < totalLen; i++)
-    {
-        if (i == firstLen)
-            values = addValues;
-
-        CSSProperty *prop = values->at(i >= firstLen ? i - firstLen : i);
-	Source source = Inline;
-
-        if( prop->m_bImportant ) source = InlineImportant;
-	if( prop->nonCSSHint ) source = NonCSSHint;
-
-	bool first;
-        // give special priority to font-xxx, color properties
-        switch(prop->m_id)
-        {
-	case CSS_PROP_FONT_STYLE:
-        case CSS_PROP_FONT_SIZE:
-	case CSS_PROP_FONT_WEIGHT:
-	case CSS_PROP_FONT_FAMILY:
-        case CSS_PROP_FONT:
-        case CSS_PROP_COLOR:
-        case CSS_PROP_BACKGROUND_IMAGE:
-	case CSS_PROP_DISPLAY:
-            // these have to be applied first, because other properties use the computed
-            // values of these porperties.
-	    first = true;
-            break;
-        default:
-            first = false;
-            break;
-        }
-
-	array->prop = prop;
-	array->pseudoId = RenderStyle::NOPSEUDO;
-	array->selector = 0;
-        array->position = i;
-	array->priority = (!first << 30) | (source << 24);
-	propsToApply[numProps++] = array++;
-    }
-    return numProps;
-}
-
 static bool subject;
 
 // modified version of the one in kurl.cpp
@@ -704,17 +734,24 @@ static void cleanpath(QString &path)
     //kdDebug() << "checkPseudoState " << path << endl;
 }
 
-static void checkPseudoState( DOM::ElementImpl *e )
+static void checkPseudoState( DOM::ElementImpl *e, bool checkVisited = true )
 {
     if (!e->hasAnchor()) {
         pseudoState = PseudoNone;
         return;
     }
+
     const AtomicString& attr = e->getAttribute(ATTR_HREF);
-    if( attr.isNull() ) {
+    if (attr.isNull()) {
         pseudoState = PseudoNone;
         return;
     }
+    
+    if (!checkVisited) {
+        pseudoState = PseudoAnyLink;
+        return;
+    }
+
     QConstString cu(attr.unicode(), attr.length());
     QString u = cu.string();
     if ( !u.contains("://") ) {
@@ -730,15 +767,12 @@ static void checkPseudoState( DOM::Eleme
     pseudoState = KHTMLFactory::vLinks()->contains( u ) ? PseudoVisited : PseudoLink;
 }
 
-void CSSStyleSelector::checkSelector(int selIndex, DOM::ElementImpl *e, RenderStyle::PseudoId pseudo)
+bool CSSStyleSelector::checkSelector(CSSSelector* sel, ElementImpl *e)
 {
     dynamicPseudo = RenderStyle::NOPSEUDO;
     
     NodeImpl *n = e;
 
-    selectorCache[ selIndex ].state = Invalid;
-    CSSSelector *sel = selectors[ selIndex ];
-
     // we have the subject part of the selector
     subject = true;
 
@@ -751,33 +785,34 @@ void CSSStyleSelector::checkSelector(int
                                sel->pseudoType() == CSSSelector::PseudoActive)));
     bool affectedByHover = style ? style->affectedByHoverRules() : false;
     bool affectedByActive = style ? style->affectedByActiveRules() : false;
-    bool havePseudo = pseudo != RenderStyle::NOPSEUDO;
+    bool havePseudo = pseudoStyle != RenderStyle::NOPSEUDO;
     
     // first selector has to match
-    if(!checkOneSelector(sel, e)) return;
+    if (!checkOneSelector(sel, e)) return false;
 
     // check the subselectors
     CSSSelector::Relation relation = sel->relation;
     while((sel = sel->tagHistory))
     {
-        if (!n->isElementNode()) return;
+        if (!n->isElementNode()) return false;
         if (relation != CSSSelector::SubSelector) {
             subject = false;
-            if (havePseudo && dynamicPseudo != pseudo)
-                return;
+            if (havePseudo && dynamicPseudo != pseudoStyle)
+                return false;
         }
         
         switch(relation)
         {
         case CSSSelector::Descendant:
         {
+            // FIXME: This match needs to know how to backtrack and be non-deterministic.
             bool found = false;
             while(!found)
             {
 		n = n->parentNode();
-                if(!n || !n->isElementNode()) return;
+                if(!n || !n->isElementNode()) return false;
                 ElementImpl *elem = static_cast<ElementImpl *>(n);
-                if(checkOneSelector(sel, elem)) found = true;
+                if (checkOneSelector(sel, elem)) found = true;
             }
             break;
         }
@@ -786,9 +821,9 @@ void CSSStyleSelector::checkSelector(int
             n = n->parentNode();
             if (!strictParsing)
                 while (n && n->implicitNode()) n = n->parentNode();
-            if(!n || !n->isElementNode()) return;
+            if(!n || !n->isElementNode()) return false;
             ElementImpl *elem = static_cast<ElementImpl *>(n);
-            if(!checkOneSelector(sel, elem)) return;
+            if (!checkOneSelector(sel, elem)) return false;
             break;
         }
         case CSSSelector::Sibling:
@@ -796,9 +831,9 @@ void CSSStyleSelector::checkSelector(int
             n = n->previousSibling();
 	    while( n && !n->isElementNode() )
 		n = n->previousSibling();
-            if( !n ) return;
+            if( !n ) return false;
             ElementImpl *elem = static_cast<ElementImpl *>(n);
-            if(!checkOneSelector(sel, elem)) return;
+            if (!checkOneSelector(sel, elem)) return false;
             break;
         }
         case CSSSelector::SubSelector:
@@ -811,10 +846,9 @@ void CSSStyleSelector::checkSelector(int
 	    //kdDebug() << "CSSOrderedRule::checkSelector" << endl;
 	    ElementImpl *elem = static_cast<ElementImpl *>(n);
 	    // a selector is invalid if something follows :first-xxx
-	    if ( dynamicPseudo != RenderStyle::NOPSEUDO ) {
-		return;
-	    }
-	    if(!checkOneSelector(sel, elem)) return;
+	    if (dynamicPseudo != RenderStyle::NOPSEUDO)
+		return false;
+	    if (!checkOneSelector(sel, elem)) return false;
 	    //kdDebug() << "CSSOrderedRule::checkSelector: passed" << endl;
 	    break;
 	}
@@ -822,31 +856,24 @@ void CSSStyleSelector::checkSelector(int
         relation = sel->relation;
     }
 
-    if (subject && havePseudo && dynamicPseudo != pseudo)
-        return;
+    if (subject && havePseudo && dynamicPseudo != pseudoStyle)
+        return false;
     
     // disallow *:hover, *:active, and *:hover:active except for links
     if (onlyHoverActive && subject) {
         if (pseudoState == PseudoUnknown)
-            checkPseudoState( e );
+            checkPseudoState(e);
 
         if (pseudoState == PseudoNone) {
             if (!affectedByHover && style->affectedByHoverRules())
                 style->setAffectedByHoverRules(false);
             if (!affectedByActive && style->affectedByActiveRules())
                 style->setAffectedByActiveRules(false);
-            return;
+            return false;
         }
     }
 
-    if ( dynamicPseudo != RenderStyle::NOPSEUDO ) {
-	selectorCache[selIndex].state = AppliesPseudo;
-	selectors[ selIndex ]->pseudoId = dynamicPseudo;
-    } else
-	selectorCache[ selIndex ].state = Applies;
-    //qDebug( "selector %d applies", selIndex );
-    //selectors[ selIndex ]->print();
-    return;
+    return true;
 }
 
 bool CSSStyleSelector::checkOneSelector(DOM::CSSSelector *sel, DOM::ElementImpl *e)
@@ -870,14 +897,16 @@ bool CSSStyleSelector::checkOneSelector(
     }
 
     if (sel->attr) {
-        if (sel->match == CSSSelector::Class)
-            return e->hasClass() && e->matchesCSSClass(sel->value, strictParsing);
-        else if (sel->match == CSSSelector::Id) {
-            if (!e->hasID()) return false;
-            const AtomicString& value = e->getAttribute(sel->attr);
-            return !((strictParsing && sel->value != value) ||
-                     (!strictParsing && !equalsIgnoreCase(sel->value, value)));
+        if (sel->match == CSSSelector::Class) {
+            if (!e->hasClass())
+                return false;
+            for (const AtomicStringList* c = e->getClassList(); c; c = c->next())
+                if (c->string() == sel->value)
+                    return true;
+            return false;
         }
+        else if (sel->match == CSSSelector::Id)
+            return e->hasID() && e->getIDAttribute() == sel->value;
 
         const AtomicString& value = e->getAttribute(sel->attr);
         if (value.isNull()) return false; // attribute is not set
@@ -1036,14 +1065,20 @@ bool CSSStyleSelector::checkOneSelector(
                 if (e == e->getDocument()->getCSSTarget())
                     return true;
                 break;
+            case CSSSelector::PseudoAnyLink:
+                if (pseudoState == PseudoUnknown)
+                    checkPseudoState(e, false);
+                if (pseudoState == PseudoAnyLink || pseudoState == PseudoLink || pseudoState == PseudoVisited)
+                    return true;
+                break;
             case CSSSelector::PseudoLink:
-                if ( pseudoState == PseudoUnknown )
+                if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
                     checkPseudoState( e );
                 if ( pseudoState == PseudoLink )
                     return true;
                 break;
             case CSSSelector::PseudoVisited:
-                if ( pseudoState == PseudoUnknown )
+                if ( pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink )
                     checkPseudoState( e );
                 if ( pseudoState == PseudoVisited )
                     return true;
@@ -1121,205 +1156,101 @@ bool CSSStyleSelector::checkOneSelector(
     return true;
 }
 
-void CSSStyleSelector::clearLists()
+// -----------------------------------------------------------------
+
+CSSRuleSet::CSSRuleSet()
 {
-    if ( selectors ) delete [] selectors;
-    if ( selectorCache ) {
-        for ( unsigned int i = 0; i < selectors_size; i++ )
-            if ( selectorCache[i].props )
-                delete [] selectorCache[i].props;
-
-        delete [] selectorCache;
-    }
-    if ( properties ) {
-	CSSOrderedProperty **prop = properties;
-	while ( *prop ) {
-	    delete (*prop);
-	    prop++;
-	}
-        delete [] properties;
+    m_idRules.setAutoDelete(true);
+    m_classRules.setAutoDelete(true);
+    m_tagRules.setAutoDelete(true);
+    m_universalRules = 0;
+    m_ruleCount = 0;
+}
+
+void CSSRuleSet::addToRuleSet(void* hash, QPtrDict<CSSRuleDataList>& dict,
+                              CSSStyleRuleImpl* rule, CSSSelector* sel)
+{
+    if (!hash) return;
+    CSSRuleDataList* rules = dict.find(hash);
+    if (!rules) {
+        rules = new CSSRuleDataList(m_ruleCount++, rule, sel);
+        dict.insert(hash, rules);
     }
-    selectors = 0;
-    properties = 0;
-    selectorCache = 0;
+    else
+        rules->append(m_ruleCount++, rule, sel);
 }
 
-
-void CSSStyleSelector::buildLists()
+void CSSRuleSet::addRule(CSSStyleRuleImpl* rule, CSSSelector* sel)
 {
-    clearLists();
-    // collect all selectors and Properties in lists. Then transer them to the array for faster lookup.
-
-    QPtrList<CSSSelector> selectorList;
-    CSSOrderedPropertyList propertyList;
-
-    if(m_medium == "print" && defaultPrintStyle)
-      defaultPrintStyle->collect( &selectorList, &propertyList, Default,
-        Default );
-    else if(defaultStyle) defaultStyle->collect( &selectorList, &propertyList,
-      Default, Default );
-      
-    if (!strictParsing && defaultQuirksStyle)
-        defaultQuirksStyle->collect( &selectorList, &propertyList, Default, Default );
-        
-    if(userStyle) userStyle->collect(&selectorList, &propertyList, User, UserImportant );
-    if(authorStyle) authorStyle->collect(&selectorList, &propertyList, Author, AuthorImportant );
-
-    selectors_size = selectorList.count();
-    selectors = new CSSSelector *[selectors_size];
-    CSSSelector *s = selectorList.first();
-    CSSSelector **sel = selectors;
-    while ( s ) {
-	*sel = s;
-	s = selectorList.next();
-	++sel;
-    }
-
-    selectorCache = new SelectorCache[selectors_size];
-    for ( unsigned int i = 0; i < selectors_size; i++ ) {
-        selectorCache[i].state = Unknown;
-        selectorCache[i].props_size = 0;
-        selectorCache[i].props = 0;
+    if (sel->match == CSSSelector::Id) {
+        addToRuleSet(sel->value.implementation(), m_idRules, rule, sel);
+        return;
     }
-
-    // presort properties. Should make the sort() calls in styleForElement faster.
-    propertyList.sort();
-    properties_size = propertyList.count() + 1;
-    properties = new CSSOrderedProperty *[ properties_size ];
-    CSSOrderedProperty *p = propertyList.first();
-    CSSOrderedProperty **prop = properties;
-    while ( p ) {
-	*prop = p;
-	p = propertyList.next();
-	++prop;
+    if (sel->match == CSSSelector::Class) {
+        addToRuleSet(sel->value.implementation(), m_classRules, rule, sel);
+        return;
     }
-    *prop = 0;
-
-    unsigned int* offsets = new unsigned int[selectors_size];
-    if(properties[0])
-	offsets[properties[0]->selector] = 0;
-    for(unsigned int p = 1; p < properties_size; ++p) {
-
-	if(!properties[p] || (properties[p]->selector != properties[p - 1]->selector)) {
-	    unsigned int sel = properties[p - 1]->selector;
-            int* newprops = new int[selectorCache[sel].props_size+2];
-            for ( unsigned int i=0; i < selectorCache[sel].props_size; i++ )
-                newprops[i] = selectorCache[sel].props[i];
-
-	    newprops[selectorCache[sel].props_size] = offsets[sel];
-	    newprops[selectorCache[sel].props_size+1] = p - offsets[sel];
-            delete [] selectorCache[sel].props;
-            selectorCache[sel].props = newprops;
-            selectorCache[sel].props_size += 2;
-
-	    if(properties[p]) {
-		sel = properties[p]->selector;
-		offsets[sel] = p;
-            }
-        }
+     
+    Q_UINT16 localName = localNamePart(sel->tag);
+    if (localName != anyLocalName) {
+        addToRuleSet((void*)(int)localName, m_tagRules, rule, sel);
+        return;
     }
-    delete [] offsets;
-}
-
-
-// ----------------------------------------------------------------------
-
-
-CSSOrderedRule::CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index)
-{
-    rule = r;
-    if(rule) r->ref();
-    index = _index;
-    selector = s;
-}
-
-CSSOrderedRule::~CSSOrderedRule()
-{
-    if(rule) rule->deref();
-}
-
-// -----------------------------------------------------------------
-
-CSSStyleSelectorList::CSSStyleSelectorList()
-    : QPtrList<CSSOrderedRule>()
-{
-    setAutoDelete(true);
-}
-CSSStyleSelectorList::~CSSStyleSelectorList()
-{
+    
+    // Just put it in the universal rule set.
+    if (!m_universalRules)
+        m_universalRules = new CSSRuleDataList(m_ruleCount++, rule, sel);
+    else
+        m_universalRules->append(m_ruleCount++, rule, sel);
 }
 
-void CSSStyleSelectorList::append( CSSStyleSheetImpl *sheet,
-                                   const DOMString &medium )
+void CSSRuleSet::addRulesFromSheet(CSSStyleSheetImpl *sheet, const DOMString &medium)
 {
-    if(!sheet || !sheet->isCSSStyleSheet()) return;
+    if (!sheet || !sheet->isCSSStyleSheet()) return;
 
-    // No media implies "all", but if a medialist exists it must
+    // No media implies "all", but if a media list exists it must
     // contain our current medium
-    if( sheet->media() && !sheet->media()->contains( medium ) )
-        return; // style sheet not applicable for this medium
+    if (sheet->media() && !sheet->media()->contains(medium))
+        return; // the style sheet doesn't apply
 
     int len = sheet->length();
 
-    for(int i = 0; i< len; i++)
-    {
+    for (int i = 0; i < len; i++) {
         StyleBaseImpl *item = sheet->item(i);
-        if(item->isStyleRule())
-        {
-            CSSStyleRuleImpl *r = static_cast<CSSStyleRuleImpl *>(item);
-            QPtrList<CSSSelector> *s = r->selector();
-            for(int j = 0; j < (int)s->count(); j++)
-            {
-                CSSOrderedRule *rule = new CSSOrderedRule(r, s->at(j), count());
-		QPtrList<CSSOrderedRule>::append(rule);
-                //kdDebug( 6080 ) << "appending StyleRule!" << endl;
-            }
+        if (item->isStyleRule()) {
+            CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(item);
+            for (CSSSelector* s = rule->selector(); s; s = s->next())
+                addRule(rule, s);
         }
-        else if(item->isImportRule())
-        {
+        else if(item->isImportRule()) {
             CSSImportRuleImpl *import = static_cast<CSSImportRuleImpl *>(item);
 
             //kdDebug( 6080 ) << "@import: Media: "
             //                << import->media()->mediaText().string() << endl;
 
-            if( !import->media() || import->media()->contains( medium ) )
-            {
-                CSSStyleSheetImpl *importedSheet = import->styleSheet();
-                append( importedSheet, medium );
-            }
+            if (!import->media() || import->media()->contains(medium))
+                addRulesFromSheet(import->styleSheet(), medium);
         }
-        else if( item->isMediaRule() )
-        {
-            CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl *>( item );
+        else if(item->isMediaRule()) {
+            CSSMediaRuleImpl *r = static_cast<CSSMediaRuleImpl*>(item);
             CSSRuleListImpl *rules = r->cssRules();
 
             //DOMString mediaText = media->mediaText();
             //kdDebug( 6080 ) << "@media: Media: "
             //                << r->media()->mediaText().string() << endl;
 
-            if( ( !r->media() || r->media()->contains( medium ) ) && rules)
-            {
-                // Traverse child elements of the @import rule. Since
-                // many elements are not allowed as child we do not use
-                // a recursive call to append() here
-                for( unsigned j = 0; j < rules->length(); j++ )
-                {
+            if ((!r->media() || r->media()->contains(medium)) && rules) {
+                // Traverse child elements of the @media rule.
+                for (unsigned j = 0; j < rules->length(); j++) {
                     //kdDebug( 6080 ) << "*** Rule #" << j << endl;
 
-                    CSSRuleImpl *childItem = rules->item( j );
-                    if( childItem->isStyleRule() )
-                    {
+                    CSSRuleImpl *childItem = rules->item(j);
+                    if (childItem->isStyleRule()) {
                         // It is a StyleRule, so append it to our list
-                        CSSStyleRuleImpl *styleRule =
-                                static_cast<CSSStyleRuleImpl *>( childItem );
-
-                        QPtrList<CSSSelector> *s = styleRule->selector();
-                        for( int j = 0; j < ( int ) s->count(); j++ )
-                        {
-                            CSSOrderedRule *orderedRule = new CSSOrderedRule(
-                                            styleRule, s->at( j ), count() );
-                	    QPtrList<CSSOrderedRule>::append( orderedRule );
-                        }
+                        CSSStyleRuleImpl* rule = static_cast<CSSStyleRuleImpl*>(childItem);
+                        for (CSSSelector* s = rule->selector(); s; s = s->next())
+                            addRule(rule, s);
+                        
                     }
                     else
                     {
@@ -1338,79 +1269,6 @@ void CSSStyleSelectorList::append( CSSSt
     }
 }
 
-
-void CSSStyleSelectorList::collect( QPtrList<CSSSelector> *selectorList, CSSOrderedPropertyList *propList,
-				    Source regular, Source important )
-{
-    CSSOrderedRule *r = first();
-    while( r ) {
-	CSSSelector *sel = selectorList->first();
-	int selectorNum = 0;
-	while( sel ) {
-	    if ( *sel == *(r->selector) )
-		break;
-	    sel = selectorList->next();
-	    selectorNum++;
-	}
-	if ( !sel )
-	    selectorList->append( r->selector );
-//	else
-//	    qDebug("merged one selector");
-	propList->append(r->rule->declaration(), selectorNum, r->selector->specificity(), regular, important );
-	r = next();
-    }
-}
-
-// -------------------------------------------------------------------------
-
-int CSSOrderedPropertyList::compareItems(QPtrCollection::Item i1, QPtrCollection::Item i2)
-{
-    int diff =  static_cast<CSSOrderedProperty *>(i1)->priority
-        - static_cast<CSSOrderedProperty *>(i2)->priority;
-    return diff ? diff : static_cast<CSSOrderedProperty *>(i1)->position
-        - static_cast<CSSOrderedProperty *>(i2)->position;
-}
-
-void CSSOrderedPropertyList::append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
-				    Source regular, Source important )
-{
-    QPtrList<CSSProperty> *values = decl->values();
-    if(!values) return;
-    int len = values->count();
-    for(int i = 0; i < len; i++)
-    {
-        CSSProperty *prop = values->at(i);
-	Source source = regular;
-
-	if( prop->m_bImportant ) source = important;
-	if( prop->nonCSSHint ) source = NonCSSHint;
-
-	bool first = false;
-        // give special priority to font-xxx, color properties
-        switch(prop->m_id)
-        {
-	case CSS_PROP_FONT_STYLE:
-        case CSS_PROP_FONT_SIZE:
-	case CSS_PROP_FONT_WEIGHT:
-	case CSS_PROP_FONT_FAMILY:
-        case CSS_PROP_FONT:
-        case CSS_PROP_COLOR:
-        case CSS_PROP_BACKGROUND_IMAGE:
-	case CSS_PROP_DISPLAY:
-            // these have to be applied first, because other properties use the computed
-            // values of these porperties.
-	    first = true;
-            break;
-        default:
-            break;
-        }
-
-	QPtrList<CSSOrderedProperty>::append(new CSSOrderedProperty(prop, selector,
-								 first, source, specificity,
-								 count() ));
-    }
-}
-
 // -------------------------------------------------------------------------------------
 // this is mostly boring stuff on how to apply a certain rule to the renderstyle...
 
@@ -1583,8 +1441,48 @@ static QColor colorForCSSValue( int css_
     return c;
 };
 
+void CSSStyleSelector::applyDeclarations(bool applyFirst, bool isImportant,
+                                         int startIndex, int endIndex)
+{
+    if (startIndex == -1) return;
+    for (int i = startIndex; i <= endIndex; i++) {
+        CSSStyleDeclarationImpl* decl = m_matchedDecls[i];
+        QPtrList<CSSProperty>* props = decl->values();
+        if (props) {
+            QPtrListIterator<CSSProperty> propertyIt(*props);
+            CSSProperty* current;
+            for (propertyIt.toFirst(); (current = propertyIt.current()); ++propertyIt) {
+                // give special priority to font-xxx, color properties
+                if (isImportant == current->isImportant()) {
+                    bool first;
+                    switch(current->id())
+                    {
+                        case CSS_PROP_FONT_STYLE:
+                        case CSS_PROP_FONT_SIZE:
+                        case CSS_PROP_FONT_WEIGHT:
+                        case CSS_PROP_FONT_FAMILY:
+                        case CSS_PROP_FONT:
+                        case CSS_PROP_COLOR:
+                        case CSS_PROP_BACKGROUND_IMAGE:
+                        case CSS_PROP_DISPLAY:
+                            // these have to be applied first, because other properties use the computed
+                            // values of these porperties.
+                            first = true;
+                            break;
+                        default:
+                            first = false;
+                            break;
+                    }
+                    
+                    if (first == applyFirst)
+                        applyProperty(current->id(), current->value());
+                }
+            }
+        }
+    }
+}
 
-void CSSStyleSelector::applyRule( int id, DOM::CSSValueImpl *value )
+void CSSStyleSelector::applyProperty( int id, DOM::CSSValueImpl *value )
 {
     //kdDebug( 6080 ) << "applying property " << prop->m_id << endl;
 
@@ -2214,20 +2112,11 @@ void CSSStyleSelector::applyRule( int id
                 col = RenderStyle::initialColor();
         }
         else {
-            if(!primitiveValue )
+            if(!primitiveValue)
                 return;
-            int ident = primitiveValue->getIdent();
-            if ( ident ) {
-                if ( ident == CSS_VAL__KHTML_TEXT )
-                    col = element->getDocument()->textColor();
-                else
-                    col = colorForCSSValue( ident );
-            } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR )
-                    col.setRgb(primitiveValue->getRGBColorValue());
-            else {
-                return;
-            }
+            col = getColorFromPrimitiveValue(primitiveValue);
         }
+
         //kdDebug( 6080 ) << "applying color " << col.isValid() << endl;
         switch(id)
         {
@@ -3139,10 +3028,10 @@ void CSSStyleSelector::applyRule( int id
             if ( !font->style || !font->variant || !font->weight ||
                  !font->size || !font->lineHeight || !font->family )
                 return;
-            applyRule( CSS_PROP_FONT_STYLE, font->style );
-            applyRule( CSS_PROP_FONT_VARIANT, font->variant );
-            applyRule( CSS_PROP_FONT_WEIGHT, font->weight );
-            applyRule( CSS_PROP_FONT_SIZE, font->size );
+            applyProperty( CSS_PROP_FONT_STYLE, font->style );
+            applyProperty( CSS_PROP_FONT_VARIANT, font->variant );
+            applyProperty( CSS_PROP_FONT_WEIGHT, font->weight );
+            applyProperty( CSS_PROP_FONT_SIZE, font->size );
 
             // Line-height can depend on font().pixelSize(), so we have to update the font
             // before we evaluate line-height, e.g., font: 1em/1em.  FIXME: Still not
@@ -3150,8 +3039,8 @@ void CSSStyleSelector::applyRule( int id
             if (fontDirty)
                 CSSStyleSelector::style->htmlFont().update( paintDeviceMetrics );
             
-            applyRule( CSS_PROP_LINE_HEIGHT, font->lineHeight );
-            applyRule( CSS_PROP_FONT_FAMILY, font->family );
+            applyProperty( CSS_PROP_LINE_HEIGHT, font->lineHeight );
+            applyProperty( CSS_PROP_FONT_FAMILY, font->family );
         }
         return;
         
@@ -3624,6 +3513,33 @@ float CSSStyleSelector::smallerFontSize(
     // FIXME: Figure out where we fall in the size ranges (xx-small to xxx-large) and scale down to
     // the next size level. 
     return size/1.2;
+}
+
+QColor CSSStyleSelector::getColorFromPrimitiveValue(CSSPrimitiveValueImpl* primitiveValue)
+{
+    QColor col;
+    int ident = primitiveValue->getIdent();
+    if (ident) {
+        if (ident == CSS_VAL__KHTML_TEXT)
+            col = element->getDocument()->textColor();
+        else if (ident == CSS_VAL__KHTML_LINK) {
+            QColor linkColor = element->getDocument()->linkColor();
+            QColor visitedColor = element->getDocument()->visitedLinkColor();
+            if (linkColor == visitedColor)
+                col = linkColor;
+            else {
+                if (pseudoState == PseudoUnknown || pseudoState == PseudoAnyLink)
+                    checkPseudoState(element);
+                col = (pseudoState == PseudoLink) ? linkColor : visitedColor;
+            }
+        }
+        else if (ident == CSS_VAL__KHTML_ACTIVELINK)
+            col = element->getDocument()->activeLinkColor();
+        else
+            col = colorForCSSValue( ident );
+    } else if ( primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_RGBCOLOR )
+        col.setRgb(primitiveValue->getRGBColorValue());
+    return col;    
 }
 
 } // namespace khtml
Index: khtml/css/cssstyleselector.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssstyleselector.h,v
retrieving revision 1.20
diff -u -p -r1.20 khtml/css/cssstyleselector.h
--- khtml/css/cssstyleselector.h	2003/11/17 20:38:09	1.20
+++ khtml/css/cssstyleselector.h	2004/02/05 01:40:11
@@ -23,10 +23,12 @@
 #ifndef _CSS_cssstyleselector_h_
 #define _CSS_cssstyleselector_h_
 
-#include <qptrlist.h>
+#include <qptrvector.h>
+#include <qptrdict.h>
 
 #include "rendering/render_style.h"
 #include "dom/dom_string.h"
+#include "css/css_ruleimpl.h"
 
 class KHTMLSettings;
 class KHTMLView;
@@ -38,10 +40,8 @@ namespace DOM {
     class NodeImpl;
     class ElementImpl;
     class StyleSheetImpl;
-    class CSSStyleRuleImpl;
     class CSSStyleSheetImpl;
     class CSSSelector;
-    class CSSStyleDeclarationImpl;
     class CSSProperty;
     class StyleSheetListImpl;
     class CSSValueImpl;
@@ -49,28 +49,11 @@ namespace DOM {
 
 namespace khtml
 {
-    class CSSStyleSelectorList;
-    class CSSOrderedRule;
-    class CSSOrderedProperty;
-    class CSSOrderedPropertyList;
+    class CSSRuleData;
+    class CSSRuleDataList;
+    class CSSRuleSet;
     class RenderStyle;
 
-    /*
-     * to remember the source where a rule came from. Differntiates between
-     * important and not important rules. This is ordered in the order they have to be applied
-     * to the RenderStyle.
-     */
-    enum Source {
-	Default = 0,
-	NonCSSHint = 1,
-        User = 2,
-	Author = 3,
-	Inline = 4,
-	AuthorImportant = 5,
-	InlineImportant = 6,
-	UserImportant =7
-    };
-
     /**
      * this class selects a RenderStyle for a given Element based on the
      * collection of styleshets it contains. This is just a vrtual base class
@@ -107,21 +90,16 @@ namespace khtml
 	 * creates a new StyleSelector for a Document.
 	 * goes through all StyleSheets defined in the document and
 	 * creates a list of rules it needs to apply to objects
-	 *
-	 * Also takes into account special cases for HTML documents,
-	 * including the defaultStyle (which is html only)
 	 */
-	CSSStyleSelector( DOM::DocumentImpl* doc, QString userStyleSheet, DOM::StyleSheetListImpl *styleSheets, const KURL &url,
-                          bool _strictParsing );
+	CSSStyleSelector(DOM::DocumentImpl* doc, QString userStyleSheet, 
+                         DOM::StyleSheetListImpl *styleSheets, const KURL &url,
+                         bool _strictParsing);
 	/**
 	 * same as above but for a single stylesheet.
 	 */
-	CSSStyleSelector( DOM::CSSStyleSheetImpl *sheet );
-
+	CSSStyleSelector(DOM::CSSStyleSheetImpl *sheet);
 	~CSSStyleSelector();
 
-	void addSheet( DOM::CSSStyleSheetImpl *sheet );
-
 	static void loadDefaultStyle(const KHTMLSettings *s = 0);
 	static void clear();
 
@@ -151,12 +129,14 @@ namespace khtml
         void setFontSize(FontDef& fontDef, float size);
         float getComputedSizeFromSpecifiedSize(bool isAbsoluteSize, float specifiedSize);
         
+        QColor getColorFromPrimitiveValue(DOM::CSSPrimitiveValueImpl* primitiveValue);
+        
     protected:
 
-	/* checks if the complete selector (which can be build up from a few CSSSelector's
-	    with given relationships matches the given Element */
-        void checkSelector(int selector, DOM::ElementImpl *e, 
-                           RenderStyle::PseudoId pseudo = RenderStyle::NOPSEUDO);
+	/* checks if a compound selector (which can consist of multiple simple selectors)
+           matches the given Element */
+        bool checkSelector(DOM::CSSSelector* selector, DOM::ElementImpl *e);
+        
 	/* checks if the selector matches the given Element */
 	bool checkOneSelector(DOM::CSSSelector *selector, DOM::ElementImpl *e);
 
@@ -164,23 +144,24 @@ namespace khtml
 	   current generic font family has changed. -dwh */
 	void checkForGenericFamilyChange(RenderStyle* aStyle, RenderStyle* aParentStyle);
 
-	/* builds up the selectors and properties lists from the CSSStyleSelectorList's */
-	void buildLists();
-	void clearLists();
-
-        unsigned int addInlineDeclarations(DOM::ElementImpl* e, DOM::CSSStyleDeclarationImpl *decl,
-                                           unsigned int numProps);
-
         void adjustRenderStyle(RenderStyle* style, DOM::ElementImpl *e);
     
+        void matchRules(CSSRuleSet* rules, int& firstRuleIndex, int& lastRuleIndex);
+        void matchRulesForList(CSSRuleDataList* rules,
+                               int& firstRuleIndex, int& lastRuleIndex);
+        void sortMatchedRules(uint firstRuleIndex, uint lastRuleIndex);
+        void addMatchedRule(CSSRuleData* rule);
+        void addMatchedDeclaration(DOM::CSSStyleDeclarationImpl* decl);
+        void applyDeclarations(bool firstPass, bool important, int startIndex, int endIndex);
+        
 	static DOM::CSSStyleSheetImpl *defaultSheet;
         static DOM::CSSStyleSheetImpl *quirksSheet;
-	static CSSStyleSelectorList *defaultStyle;
-        static CSSStyleSelectorList *defaultQuirksStyle;
-	static CSSStyleSelectorList *defaultPrintStyle;
-	CSSStyleSelectorList *authorStyle;
-        CSSStyleSelectorList *userStyle;
-        DOM::CSSStyleSheetImpl *userSheet;
+	static CSSRuleSet* defaultStyle;
+        static CSSRuleSet* defaultQuirksStyle;
+	static CSSRuleSet* defaultPrintStyle;
+	CSSRuleSet* m_authorStyle;
+        CSSRuleSet* m_userStyle;
+        DOM::CSSStyleSheetImpl* m_userSheet;
 
 public:
 	static RenderStyle* styleNotYetAvailable;
@@ -188,52 +169,30 @@ public:
     private:
         void init();
 
-    public: // we need to make the enum public for SelectorCache
-	enum SelectorState {
-	    Unknown = 0,
-	    Applies,
-	    AppliesPseudo,
-	    Invalid
-	};
-
-        enum SelectorMedia {
-            MediaAural = 1,
-            MediaBraille,
-            MediaEmboss,
-            MediaHandheld,
-            MediaPrint,
-            MediaProjection,
-            MediaScreen,
-            MediaTTY,
-            MediaTV
-        };
     protected:
-
-        struct SelectorCache {
-            SelectorState state;
-            unsigned int props_size;
-            int *props;
-        };
-
-	unsigned int selectors_size;
-	DOM::CSSSelector **selectors;
-	SelectorCache *selectorCache;
-	unsigned int properties_size;
-	CSSOrderedProperty **properties;
-	QMemArray<CSSOrderedProperty> inlineProps;
+        // We collect the set of decls that match in |m_matchedDecls|.  We then walk the
+        // set of matched decls four times, once for those properties that others depend on (like font-size),
+        // and then a second time for all the remaining properties.  We then do the same two passes
+        // for any !important rules.
+        QMemArray<DOM::CSSStyleDeclarationImpl*> m_matchedDecls;
+        unsigned m_matchedDeclCount;
+        
+        // A buffer used to hold the set of matched rules for an element, and a temporary buffer used for
+        // merge sorting.
+        QMemArray<CSSRuleData*> m_matchedRules;
+        unsigned m_matchedRuleCount;
+        QMemArray<CSSRuleData*> m_tmpRules;
+        unsigned m_tmpRuleCount;
+        
         QString m_medium;
-	CSSOrderedProperty **propsToApply;
-	CSSOrderedProperty **pseudoProps;
-	unsigned int propsToApplySize;
-	unsigned int pseudoPropsSize;
 
-
 	RenderStyle::PseudoId dynamicPseudo;
 	
 	RenderStyle *style;
 	RenderStyle *parentStyle;
 	DOM::ElementImpl *element;
 	DOM::NodeImpl *parentNode;
+        RenderStyle::PseudoId pseudoStyle;
 	KHTMLView *view;
 	KHTMLPart *part;
 	const KHTMLSettings *settings;
@@ -241,79 +200,69 @@ public:
         bool fontDirty;
         bool isXMLDoc;
         
-	void applyRule(int id, DOM::CSSValueImpl *value);
+	void applyProperty(int id, DOM::CSSValueImpl *value);
     };
 
-    /*
-     * List of properties that get applied to the Element. We need to collect them first
-     * and then apply them one by one, because we have to change the apply order.
-     * Some properties depend on other one already being applied (for example all properties spezifying
-     * some length need to have already the correct font size. Same applies to color
-     *
-     * While sorting them, we have to take care not to mix up the original order.
-     */
-    class CSSOrderedProperty
-    {
+    class CSSRuleData {
     public:
-	CSSOrderedProperty(DOM::CSSProperty *_prop, uint _selector,
-			   bool first, Source source, unsigned int specificity,
-			   unsigned int _position )
-	    : prop ( _prop ), pseudoId( RenderStyle::NOPSEUDO ), selector( _selector ),
-	      position( _position )
-	{
-	    priority = (!first << 30) | (source << 24) | specificity;
-	}
-
-	bool operator < ( const CSSOrderedProperty &other ) const {
-             if (priority < other.priority) return true;
-             if (priority > other.priority) return false;
-             if (position < other.position) return true;
-             return false;
-	}
-
-	DOM::CSSProperty *prop;
-	RenderStyle::PseudoId pseudoId;
-	unsigned int selector;
-	unsigned int position;
+        CSSRuleData(uint pos, DOM::CSSStyleRuleImpl* r, DOM::CSSSelector* sel, CSSRuleData* prev = 0)
+        :m_position(pos), m_rule(r), m_selector(sel), m_next(0) { if (prev) prev->m_next = this; }
+        ~CSSRuleData() { delete m_next; }
 
-	Q_UINT32 priority;
+        uint position() { return m_position; }
+        DOM::CSSStyleRuleImpl* rule() { return m_rule; }
+        DOM::CSSSelector* selector() { return m_selector; }
+        CSSRuleData* next() { return m_next; }
+        
+    private:
+        uint m_position;
+        DOM::CSSStyleRuleImpl* m_rule;
+        DOM::CSSSelector* m_selector;
+        CSSRuleData* m_next;
     };
 
-    /*
-     * This is the list we will collect all properties we need to apply in.
-     * It will get sorted once before applying.
-     */
-    class CSSOrderedPropertyList : public QPtrList<CSSOrderedProperty>
-    {
+    class CSSRuleDataList {
     public:
-	virtual int compareItems(QPtrCollection::Item i1, QPtrCollection::Item i2);
-	void append(DOM::CSSStyleDeclarationImpl *decl, uint selector, uint specificity,
-		    Source regular, Source important );
-    };
+        CSSRuleDataList(uint pos, DOM::CSSStyleRuleImpl* rule, DOM::CSSSelector* sel)
+        { m_first = m_last = new CSSRuleData(pos, rule, sel); }
+        ~CSSRuleDataList() { delete m_first; }
 
-    class CSSOrderedRule
+        CSSRuleData* first() { return m_first; }
+        CSSRuleData* last() { return m_last; }
+        
+        void append(uint pos, DOM::CSSStyleRuleImpl* rule, DOM::CSSSelector* sel) {
+            m_last = new CSSRuleData(pos, rule, sel, m_last);
+        }
+        
+    private:
+        CSSRuleData* m_first;
+        CSSRuleData* m_last;
+    };
+    
+    class CSSRuleSet
     {
     public:
-	CSSOrderedRule(DOM::CSSStyleRuleImpl *r, DOM::CSSSelector *s, int _index);
-	~CSSOrderedRule();
+        CSSRuleSet();
+        ~CSSRuleSet() { delete m_universalRules; }
 
-	DOM::CSSSelector *selector;
-	DOM::CSSStyleRuleImpl *rule;
-	int index;
-    };
+        void addRulesFromSheet(DOM::CSSStyleSheetImpl* sheet, const DOM::DOMString &medium = "screen");
 
-    class CSSStyleSelectorList : public QPtrList<CSSOrderedRule>
-    {
-    public:
-	CSSStyleSelectorList();
-	virtual ~CSSStyleSelectorList();
+        void addRule(DOM::CSSStyleRuleImpl* rule, DOM::CSSSelector* sel);
+        void addToRuleSet(void* hash, QPtrDict<CSSRuleDataList>& dict,
+                          DOM::CSSStyleRuleImpl* rule, DOM::CSSSelector* sel);
 
-	void append( DOM::CSSStyleSheetImpl *sheet,
-                 const DOM::DOMString &medium = "screen" );
+        CSSRuleDataList* getIDRules(void* hash) { return m_idRules.find(hash); }
+        CSSRuleDataList* getClassRules(void* hash) { return m_classRules.find(hash); }
+        CSSRuleDataList* getTagRules(void* hash) { return m_tagRules.find(hash); }
+        CSSRuleDataList* getUniversalRules() { return m_universalRules; }
 
-	void collect( QPtrList<DOM::CSSSelector> *selectorList, CSSOrderedPropertyList *propList,
-		      Source regular, Source important );
+    public:
+        QPtrDict<CSSRuleDataList> m_idRules;
+        QPtrDict<CSSRuleDataList> m_classRules;
+        QPtrDict<CSSRuleDataList> m_tagRules;
+        CSSRuleDataList*          m_universalRules;
+        
+        uint m_ruleCount;
     };
-
 };
 #endif
Index: khtml/css/cssvalues.in
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/cssvalues.in,v
retrieving revision 1.19
diff -u -p -r1.19 khtml/css/cssvalues.in
--- khtml/css/cssvalues.in	2004/01/23 18:55:45	1.19
+++ khtml/css/cssvalues.in	2004/02/05 01:40:11
@@ -120,6 +120,8 @@ teal
 white
 yellow
 transparent
+-khtml-link
+-khtml-activelink
 activeborder
 activecaption
 appworkspace
Index: khtml/css/html4.css
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/html4.css,v
retrieving revision 1.61
diff -u -p -r1.61 khtml/css/html4.css
--- khtml/css/html4.css	2004/01/27 06:27:36	1.61
+++ khtml/css/html4.css	2004/02/05 01:40:11
@@ -419,29 +419,15 @@ SUP { 
 	font-size: smaller;
 }
 
-/* ### not supported at the moment
-ABBR, ACRONYM { 
-	font-variant: small-caps; 
-	letter-spacing: 0.1em 
-}
-*/
 abbr, 
 acronym {
 	font-style: italic;
 }
 
-*|:focus          { outline: auto 3px #1f5ccf }
-a:link          { color: #0000EE; text-decoration: underline; }
-a:link:active          { color: red }
-a:visited              { color: #551A8B; text-decoration: underline; }
-a:visited:active       { color: red }
-
-/* ### :before is now supported, but we haven't tried reinstating this
-   ### rule that was comment out long ago.
-      BR:before       { content: "\n" }
-*/
+:focus          { outline: auto 3px #1f5ccf }
+a:-khtml-any-link { color: -khtml-link; text-decoration: underline; }
+a:-khtml-any-link:active { color: -khtml-activelink; }
 
-
 /* Bidirectionality settings (do not change) */
 
 BDO[DIR="ltr"]  { 
@@ -497,19 +483,3 @@ wbr {
 }
 
 /* noscript is handled internally, as it depends on the html settings */
-
-/* media rules are commented out for the moment. We'll have to add
- * them later. Lars, 23.12.99
- */
-
-/*
-      @media print {
-        @page         { margin: 10% }
-        H1, H2, H3,
-        H4, H5, H6    { page-break-after: avoid; page-break-inside: avoid }
-        BLOCKQUOTE,
-        PRE           { page-break-inside: avoid }
-        UL, OL, DL    { page-break-before: avoid }
-      }
-
-*/
Index: khtml/css/parser.y
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/css/parser.y,v
retrieving revision 1.25
diff -u -p -r1.25 khtml/css/parser.y
--- khtml/css/parser.y	2004/01/27 19:08:34	1.25
+++ khtml/css/parser.y	2004/02/05 01:40:12
@@ -86,7 +86,6 @@ static inline int getValueID(const char 
 %union {
     CSSRuleImpl *rule;
     CSSSelector *selector;
-    QPtrList<CSSSelector> *selectorList;
     bool ok;
     MediaListImpl *mediaList;
     CSSMediaRuleImpl *mediaRule;
@@ -208,7 +207,7 @@ static int cssyylex( YYSTYPE *yylval ) {
 %type <selector> specifier_list
 %type <selector> simple_selector
 %type <selector> selector
-%type <selectorList> selector_list
+%type <selector> selector_list
 %type <selector> class
 %type <selector> attrib
 %type <selector> pseudo
@@ -493,11 +492,11 @@ ruleset:
 #endif
 	CSSParser *p = static_cast<CSSParser *>(parser);
 	if ( $1 && $4 && p->numParsedProperties ) {
-	    CSSStyleRuleImpl *rule = new CSSStyleRuleImpl( p->styleElement );
-	    CSSStyleDeclarationImpl *decl = p->createStyleDeclaration( rule );
-	    rule->setSelector( $1 );
-	    rule->setDeclaration(decl);
-	    $$ = rule;
+            CSSStyleRuleImpl *rule = new CSSStyleRuleImpl( p->styleElement );
+            CSSStyleDeclarationImpl *decl = p->createStyleDeclaration( rule );
+            rule->setSelector( $1 );
+            rule->setDeclaration(decl);
+            $$ = rule;
 	} else {
 	    $$ = 0;
 	    delete $1;
@@ -509,13 +508,11 @@ ruleset:
 selector_list:
     selector {
 	if ( $1 ) {
-	    $$ = new QPtrList<CSSSelector>;
-            $$->setAutoDelete( true );
+	    $$ = $1;
 #ifdef CSS_DEBUG
 	    kdDebug( 6080 ) << "   got simple selector:" << endl;
 	    $1->print();
 #endif
-	    $$->append( $1 );
 	} else {
 	    $$ = 0;
 	}
@@ -646,7 +643,6 @@ element_name:
 specifier_list:
     specifier {
 	$$ = $1;
-	$$->nonCSSHint = static_cast<CSSParser *>(parser)->nonCSSHint;
     }
     | specifier_list specifier {
 	$$ = $1;
@@ -669,6 +665,9 @@ specifier:
 	$$ = new CSSSelector();
 	$$->match = CSSSelector::Id;
 	$$->attr = ATTR_ID;
+        CSSParser *p = static_cast<CSSParser *>(parser);
+        if (!p->strict)
+            $1.lower();
 	$$->value = atomicString($1);
     }
   | class
@@ -678,9 +677,12 @@ specifier:
 
 class:
     '.' IDENT {
-	$$ = new CSSSelector();
+        $$ = new CSSSelector();
 	$$->match = CSSSelector::Class;
 	$$->attr = ATTR_CLASS;
+        CSSParser *p = static_cast<CSSParser *>(parser);
+        if (!p->strict)
+            $2.lower();
 	$$->value = atomicString($2);
     }
   ;
Index: khtml/dom/dom_element.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/dom/dom_element.cpp,v
retrieving revision 1.7
diff -u -p -r1.7 khtml/dom/dom_element.cpp
--- khtml/dom/dom_element.cpp	2004/01/30 07:44:44	1.7
+++ khtml/dom/dom_element.cpp	2004/02/05 01:40:12
@@ -293,7 +293,7 @@ bool Element::isHTMLElement() const
 
 CSSStyleDeclaration Element::style()
 {
-    if (impl) return ((ElementImpl *)impl)->styleRules();
+    if (impl) return ((ElementImpl *)impl)->getInlineStyleDecl();
     return 0;
 }
 
Index: khtml/html/html_baseimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/html_baseimpl.cpp,v
retrieving revision 1.50
diff -u -p -r1.50 khtml/html/html_baseimpl.cpp
--- khtml/html/html_baseimpl.cpp	2004/01/30 07:44:44	1.50
+++ khtml/html/html_baseimpl.cpp	2004/02/05 01:40:12
@@ -50,14 +50,14 @@ using namespace khtml;
 
 HTMLBodyElementImpl::HTMLBodyElementImpl(DocumentPtr *doc)
     : HTMLElementImpl(doc),
-    m_bgSet( false ), m_fgSet( false )
+    m_bgSet( false ), m_fgSet( false ), m_linkDecl(0)
 {
-    m_styleSheet = 0;
 }
 
 HTMLBodyElementImpl::~HTMLBodyElementImpl()
 {
-    if(m_styleSheet) m_styleSheet->deref();
+    if (m_linkDecl)
+        m_linkDecl->deref();
 }
 
 NodeImpl::Id HTMLBodyElementImpl::id() const
@@ -65,6 +65,16 @@ NodeImpl::Id HTMLBodyElementImpl::id() c
     return ID_BODY;
 }
 
+void HTMLBodyElementImpl::createLinkDecl()
+{
+    m_linkDecl = new CSSStyleDeclarationImpl(0);
+    m_linkDecl->ref();
+    m_linkDecl->setParent(getDocument()->elementSheet());
+    m_linkDecl->parent()->ref();
+    m_linkDecl->setNode(this);
+    m_linkDecl->setStrictParsing(!getDocument()->inCompatMode());
+}
+
 void HTMLBodyElementImpl::parseAttribute(AttributeImpl *attr)
 {
     switch(attr->id())
@@ -111,22 +121,32 @@ void HTMLBodyElementImpl::parseAttribute
     case ATTR_ALINK:
     case ATTR_LINK:
     {
-        if(!m_styleSheet) {
-            m_styleSheet = new CSSStyleSheetImpl(this,DOMString(),true);
-            m_styleSheet->ref();
+        if (attr->isNull()) {
+            if (attr->id() == ATTR_LINK)
+                getDocument()->resetLinkColor();
+            else if (attr->id() == ATTR_VLINK)
+                getDocument()->resetVisitedLinkColor();
+            else
+                getDocument()->resetActiveLinkColor();
+        }
+        else {
+            if (!m_linkDecl)
+                createLinkDecl();
+            m_linkDecl->setProperty(CSS_PROP_COLOR, attr->value(), false, false);
+            CSSValueImpl* val = m_linkDecl->getPropertyCSSValue(CSS_PROP_COLOR);
+            if (val && val->isPrimitiveValue()) {
+                QColor col = getDocument()->styleSelector()->getColorFromPrimitiveValue(static_cast<CSSPrimitiveValueImpl*>(val));
+                if (attr->id() == ATTR_LINK)
+                    getDocument()->setLinkColor(col);
+                else if (attr->id() == ATTR_VLINK)
+                    getDocument()->setVisitedLinkColor(col);
+                else
+                    getDocument()->setActiveLinkColor(col);
+            }
         }
-        QString aStr;
-	if ( attr->id() == ATTR_LINK )
-	    aStr = "a:link";
-	else if ( attr->id() == ATTR_VLINK )
-	    aStr = "a:visited";
-	else if ( attr->id() == ATTR_ALINK )
-            aStr = "a:link:active, a:visited:active";
-	aStr += " { color: " + attr->value().string() + "; }";
-        m_styleSheet->parseString(aStr, !getDocument()->inCompatMode());
-        m_styleSheet->setNonCSSHints();
+        
         if (attached())
-            getDocument()->updateStyleSelector();
+            getDocument()->recalcStyle(Force);
         break;
     }
     case ATTR_ONLOAD:
Index: khtml/html/html_baseimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/html_baseimpl.h,v
retrieving revision 1.18
diff -u -p -r1.18 khtml/html/html_baseimpl.h
--- khtml/html/html_baseimpl.h	2004/01/30 07:44:44	1.18
+++ khtml/html/html_baseimpl.h	2004/02/05 01:40:12
@@ -58,13 +58,13 @@ public:
 
     virtual void parseAttribute(AttributeImpl *);
     virtual void insertedIntoDocument();
-    
-    CSSStyleSheetImpl *sheet() const { return m_styleSheet; }
 
+    void createLinkDecl();
+
 protected:
-    CSSStyleSheetImpl *m_styleSheet;
     bool m_bgSet;
     bool m_fgSet;
+    CSSStyleDeclarationImpl* m_linkDecl;
 };
 
 // -------------------------------------------------------------------------
Index: khtml/html/html_elementimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/html_elementimpl.cpp,v
retrieving revision 1.29
diff -u -p -r1.29 khtml/html/html_elementimpl.cpp
--- khtml/html/html_elementimpl.cpp	2004/01/30 21:00:38	1.29
+++ khtml/html/html_elementimpl.cpp	2004/02/05 01:40:12
@@ -45,6 +45,7 @@
 #include "css/css_stylesheetimpl.h"
 #include "css/cssproperties.h"
 #include "css/cssvalues.h"
+#include "css/css_ruleimpl.h"
 #include "xml/dom_textimpl.h"
 #include "xml/dom2_eventsimpl.h"
 
@@ -67,12 +68,16 @@ bool HTMLNamedAttrMapImpl::isHTMLAttribu
     return true;
 }
 
-void HTMLNamedAttrMapImpl::parseClassAttribute(const DOMString& classAttr)
+void HTMLNamedAttrMapImpl::parseClassAttribute(const DOMString& classStr)
 {
     m_classList.clear();
     if (!element->hasClass())
         return;
     
+    DOMString classAttr = element->getDocument()->inCompatMode() ? 
+        (classStr.implementation()->isLower() ? classStr : DOMString(classStr.implementation()->lower())) :
+        classStr;
+    
     if (classAttr.find(' ') == -1)
         m_classList.setString(AtomicString(classAttr));
     else {
@@ -97,30 +102,21 @@ void HTMLNamedAttrMapImpl::parseClassAtt
     }
 }
 
-bool HTMLNamedAttrMapImpl::matchesCSSClass(const AtomicString& c, bool caseSensitive) const
-{
-    for (const AtomicStringList* curr = &m_classList; curr; curr = curr->next()) {
-        if (caseSensitive) {
-            if (c == curr->string())
-                return true;
-        }
-        else {
-            if (equalsIgnoreCase(c, curr->string()))
-                return true;
-        }
-    }
-    return false;
-}
-
 // ------------------------------------------------------------------
 
 HTMLElementImpl::HTMLElementImpl(DocumentPtr *doc)
     : ElementImpl(doc)
 {
+    m_inlineStyleDecl = 0;
+    m_attributeStyleDecl = 0;    
 }
 
 HTMLElementImpl::~HTMLElementImpl()
 {
+    if (m_inlineStyleDecl)
+        m_inlineStyleDecl->deref();
+    if (m_attributeStyleDecl)
+        m_attributeStyleDecl->deref();
 }
 
 bool HTMLElementImpl::isInline() const
@@ -165,6 +161,26 @@ bool HTMLElementImpl::isInline() const
     }
 }
 
+void HTMLElementImpl::createInlineStyleDecl()
+{
+    m_inlineStyleDecl = new CSSStyleDeclarationImpl(0);
+    m_inlineStyleDecl->ref();
+    m_inlineStyleDecl->setParent(getDocument()->elementSheet());
+    m_inlineStyleDecl->parent()->ref();
+    m_inlineStyleDecl->setNode(this);
+    m_inlineStyleDecl->setStrictParsing(!getDocument()->inCompatMode());
+}
+
+void HTMLElementImpl::createMappedAttributeDecl()
+{
+    m_attributeStyleDecl = new CSSStyleDeclarationImpl(0);
+    m_attributeStyleDecl->ref();
+    m_attributeStyleDecl->setParent(getDocument()->elementSheet());
+    m_attributeStyleDecl->parent()->ref();
+    m_attributeStyleDecl->setNode(this);
+    m_attributeStyleDecl->setStrictParsing(!getDocument()->inCompatMode());
+}
+
 void HTMLElementImpl::parseAttribute(AttributeImpl *attr)
 {
     DOMString indexstring;
@@ -184,6 +200,14 @@ void HTMLElementImpl::parseAttribute(Att
     case ATTR_ID:
         // unique id
         setHasID(!attr->isNull());
+        if (namedAttrMap) {
+            if (attr->isNull())
+                namedAttrMap->setID(nullAtom);
+            else if (getDocument()->inCompatMode() && !attr->value().implementation()->isLower())
+                namedAttrMap->setID(AtomicString(attr->value().implementation()->lower()));
+            else
+                namedAttrMap->setID(attr->value());
+        }
         setChanged();
         break;
     case ATTR_CLASS:
@@ -203,8 +227,8 @@ void HTMLElementImpl::parseAttribute(Att
         // ### the inline sheet ay contain more than 1 property!
         // stylesheet info
         setHasStyle();
-        if(!m_styleDecls) createDecl();
-        m_styleDecls->setProperty(attr->value());
+        if (!m_inlineStyleDecl) createInlineStyleDecl();
+        m_inlineStyleDecl->setProperty(attr->value());
         setChanged();
         break;
     case ATTR_TABINDEX:
@@ -283,37 +307,54 @@ void HTMLElementImpl::createAttributeMap
     namedAttrMap = new HTMLNamedAttrMapImpl(const_cast<HTMLElementImpl*>(this));
     namedAttrMap->ref();
 }
+
+CSSStyleDeclarationImpl* HTMLElementImpl::inlineStyleDecl() const
+{ 
+    return m_inlineStyleDecl;
+}
+
+CSSStyleDeclarationImpl* HTMLElementImpl::attributeStyleDecl() const
+{
+    return m_attributeStyleDecl;
+}
+
+CSSStyleDeclarationImpl* HTMLElementImpl::getInlineStyleDecl()
+{
+    if (!m_inlineStyleDecl)
+        createInlineStyleDecl();
+    return m_inlineStyleDecl;
+}
 
-bool HTMLElementImpl::matchesCSSClass(const AtomicString& c, bool cs) const
+const AtomicStringList* HTMLElementImpl::getClassList() const
 {
-    return namedAttrMap ? static_cast<HTMLNamedAttrMapImpl*>(namedAttrMap)->matchesCSSClass(c, cs) : false;
+    return namedAttrMap ? static_cast<HTMLNamedAttrMapImpl*>(namedAttrMap)->getClassList() : 0;
 }
 
 void HTMLElementImpl::addCSSProperty(int id, const DOMString &value)
 {
-    if(!m_styleDecls) createDecl();
-    m_styleDecls->setProperty(id, value, false, true);
+    if (!m_attributeStyleDecl) createMappedAttributeDecl();
+    m_attributeStyleDecl->setProperty(id, value, false);
     setChanged();
 }
 
 void HTMLElementImpl::addCSSProperty(int id, int value)
 {
-    if(!m_styleDecls) createDecl();
-    m_styleDecls->setProperty(id, value, false, true);
+    if (!m_attributeStyleDecl) createMappedAttributeDecl();
+    m_attributeStyleDecl->setProperty(id, value, false);
     setChanged();
 }
 
 void HTMLElementImpl::addCSSStringProperty(int id, const DOMString &value, CSSPrimitiveValue::UnitTypes type)
 {
-    if(!m_styleDecls) createDecl();
-    m_styleDecls->setStringProperty(id, value, type, false, true);
+    if (!m_attributeStyleDecl) createMappedAttributeDecl();
+    m_attributeStyleDecl->setStringProperty(id, value, type, false);
     setChanged();
 }
 
 void HTMLElementImpl::addCSSImageProperty(int id, const DOMString &URL)
 {
-    if(!m_styleDecls) createDecl();
-    m_styleDecls->setImageProperty(id, URL, false, true);
+    if (!m_attributeStyleDecl) createMappedAttributeDecl();
+    m_attributeStyleDecl->setImageProperty(id, URL, false);
     setChanged();
 }
 
@@ -321,7 +362,7 @@ void HTMLElementImpl::addCSSLength(int i
 {
     // FIXME: This function should not spin up the CSS parser, but should instead just figure out the correct
     // length unit and make the appropriate parsed value.
-    if(!m_styleDecls) createDecl();
+    if (!m_attributeStyleDecl) createMappedAttributeDecl();
 
     // strip attribute garbage..
     DOMStringImpl* v = value.implementation();
@@ -336,13 +377,13 @@ void HTMLElementImpl::addCSSLength(int i
                 break;
         }
         if ( l != v->l ) {
-            m_styleDecls->setLengthProperty( id, DOMString( v->s, l ), false, true );
+            m_attributeStyleDecl->setLengthProperty(id, DOMString( v->s, l ), false);
             setChanged();
             return;
         }
     }
 
-    m_styleDecls->setLengthProperty(id, value, false, true);
+    m_attributeStyleDecl->setLengthProperty(id, value, false);
     setChanged();
 }
 
@@ -365,13 +406,13 @@ static inline int toHex( const QChar &c 
 /* color parsing that tries to match as close as possible IE 6. */
 void HTMLElementImpl::addHTMLColor( int id, const DOMString &c )
 {
-    if(!m_styleDecls) createDecl();
+    if (!m_attributeStyleDecl) createMappedAttributeDecl();
 
     // this is the only case no color gets applied in IE.
     if ( !c.length() )
         return;
 
-    if ( m_styleDecls->setProperty(id, c, false, true) )
+    if ( m_attributeStyleDecl->setProperty(id, c, false) )
         return;
 
     QString color = c.string();
@@ -434,21 +475,21 @@ void HTMLElementImpl::addHTMLColor( int 
 
             color.sprintf("#%02x%02x%02x", colors[0], colors[1], colors[2] );
             // 	    qDebug( "trying to add fixed color string '%s'", color.latin1() );
-            if ( m_styleDecls->setProperty(id, DOMString(color), false, true) )
+            if ( m_attributeStyleDecl->setProperty(id, DOMString(color), false) )
                 return;
         }
     }
-    m_styleDecls->setProperty(id, CSS_VAL_BLACK, false, true);
+    m_attributeStyleDecl->setProperty(id, CSS_VAL_BLACK, false);
 }
 
 void HTMLElementImpl::removeCSSProperty(int id)
 {
-    if(!m_styleDecls)
+    if(!m_attributeStyleDecl)
         return;
-    m_styleDecls->parent()->deref();
-    m_styleDecls->setParent(getDocument()->elementSheet());
-    m_styleDecls->parent()->ref();
-    m_styleDecls->removeProperty(id);
+    m_attributeStyleDecl->parent()->deref();
+    m_attributeStyleDecl->setParent(getDocument()->elementSheet());
+    m_attributeStyleDecl->parent()->ref();
+    m_attributeStyleDecl->removeProperty(id);
     setChanged();
 }
 
Index: khtml/html/html_elementimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/html_elementimpl.h,v
retrieving revision 1.16
diff -u -p -r1.16 khtml/html/html_elementimpl.h
--- khtml/html/html_elementimpl.h	2004/01/30 07:44:44	1.16
+++ khtml/html/html_elementimpl.h	2004/02/05 01:40:12
@@ -43,7 +43,7 @@ public:
     virtual bool isHTMLAttributeMap() const;
     
     virtual void parseClassAttribute(const DOMString& classAttr);
-    bool matchesCSSClass(const AtomicString& c, bool caseSensitive) const;
+    const AtomicStringList* getClassList() const { return &m_classList; }
     
 private:
     AtomicStringList m_classList;
@@ -65,7 +65,7 @@ public:
     virtual void parseAttribute(AttributeImpl *token);
     virtual void createAttributeMap() const;
 
-    virtual bool matchesCSSClass(const AtomicString& c, bool caseSensitive) const;
+     virtual const AtomicStringList* getClassList() const;
 
     void addCSSLength(int id, const DOMString &value); // FIXME: value will be parsed by the CSS parser
     void addCSSProperty(int id, const DOMString &value); // value will be parsed by the CSS parser
@@ -90,6 +90,12 @@ public:
 
     virtual void click();
     
+    virtual CSSStyleDeclarationImpl* inlineStyleDecl() const;
+    virtual CSSStyleDeclarationImpl* attributeStyleDecl() const;
+    virtual CSSStyleDeclarationImpl* getInlineStyleDecl();
+    void createInlineStyleDecl();
+    void createMappedAttributeDecl();
+    
 #if APPLE_CHANGES
     virtual bool isGenericFormElement() const { return false; }
 #endif
@@ -99,6 +105,9 @@ public:
 protected:
     // for IMG, OBJECT and APPLET
     void addHTMLAlignment( const DOMString& alignment );
+    
+    CSSStyleDeclarationImpl* m_inlineStyleDecl;
+    CSSStyleDeclarationImpl* m_attributeStyleDecl;
 };
 
 class HTMLGenericElementImpl : public HTMLElementImpl
Index: khtml/html/html_tableimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/html_tableimpl.cpp,v
retrieving revision 1.36
diff -u -p -r1.36 khtml/html/html_tableimpl.cpp
--- khtml/html/html_tableimpl.cpp	2004/01/30 07:44:44	1.36
+++ khtml/html/html_tableimpl.cpp	2004/02/05 01:40:12
@@ -94,15 +94,15 @@ DOM::CSSStyleDeclarationImpl* HTMLTableE
         m_sharedCellDecls->setStrictParsing( !getDocument()->inCompatMode() );
 
         if (m_noBorder)
-            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_WIDTH, "0", false, true);
+            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_WIDTH, "0", false);
         else {
-            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_WIDTH, "1px", false, true);
+            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_WIDTH, "1px", false);
             int v = m_solid ? CSS_VAL_SOLID : CSS_VAL_INSET;
-            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_TOP_STYLE, v, false, true);
-            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v, false, true);
-            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_LEFT_STYLE, v, false, true);
-            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, v, false, true);
-            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_COLOR, "inherit", false, true);
+            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_TOP_STYLE, v, false);
+            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_BOTTOM_STYLE, v, false);
+            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_LEFT_STYLE, v, false);
+            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_RIGHT_STYLE, v, false);
+            m_sharedCellDecls->setProperty(CSS_PROP_BORDER_COLOR, "inherit", false);
         }
     }
     
@@ -890,7 +890,7 @@ void HTMLTableCellElementImpl::parseAttr
 }
 
 // used by table cells to share style decls created by the enclosing table.
-DOM::CSSStyleDeclarationImpl* HTMLTableCellElementImpl::getAdditionalStyleDecls()
+CSSStyleDeclarationImpl* HTMLTableCellElementImpl::additionalAttributeStyleDecl()
 {
     HTMLElementImpl* p = static_cast<HTMLElementImpl*>(parentNode());
     while(p && p->id() != ID_TABLE)
Index: khtml/html/html_tableimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/html/html_tableimpl.h,v
retrieving revision 1.12
diff -u -p -r1.12 khtml/html/html_tableimpl.h
--- khtml/html/html_tableimpl.h	2003/02/17 20:25:57	1.12
+++ khtml/html/html_tableimpl.h	2004/02/05 01:40:12
@@ -203,7 +203,7 @@ public:
     virtual void attach();
 
     // used by table cells to share style decls created by the enclosing table.
-    virtual DOM::CSSStyleDeclarationImpl* getAdditionalStyleDecls();
+    virtual CSSStyleDeclarationImpl* additionalAttributeStyleDecl();
     
 protected:
     int _row;
Index: khtml/xml/dom_atomicstring.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_atomicstring.cpp,v
retrieving revision 1.2
diff -u -p -r1.2 khtml/xml/dom_atomicstring.cpp
--- khtml/xml/dom_atomicstring.cpp	2004/02/02 18:42:37	1.2
+++ khtml/xml/dom_atomicstring.cpp	2004/02/05 01:40:12
@@ -134,6 +134,7 @@ DOMStringImpl *AtomicString::add(const c
     
     DOMStringImpl *r = new DOMStringImpl(c, length);
     r->_hash = hash;
+    r->_inTable = true;
     
     _table[i] = r;
     ++_keyCount;
@@ -170,6 +171,7 @@ DOMStringImpl *AtomicString::add(const Q
     
     DOMStringImpl *r = new DOMStringImpl(s, length);
     r->_hash = hash;
+    r->_inTable = true;
     
     _table[i] = r;
     ++_keyCount;
@@ -182,8 +184,8 @@ DOMStringImpl *AtomicString::add(const Q
 
 DOMStringImpl *AtomicString::add(DOMStringImpl *r)
 {
-    if (!r)
-        return 0;
+    if (!r || r->_inTable)
+        return r;
 
     if (r->l == 0)
         return DOMStringImpl::empty();
@@ -199,11 +201,13 @@ DOMStringImpl *AtomicString::add(DOMStri
     numCollisions += _table[i] && !equal(_table[i], r);
 #endif
     while (DOMStringImpl *key = _table[i]) {
-        if (equal(key, r))
+        if (equal(key, r)) {
             return key;
+        }
         i = (i + 1) & _tableSizeMask;
     }
 
+    r->_inTable = true;
     _table[i] = r;
     ++_keyCount;
     
@@ -230,7 +234,7 @@ inline void AtomicString::insert(DOMStri
 
 void AtomicString::remove(DOMStringImpl *r)
 {
-    unsigned hash = r->hash();
+    unsigned hash = r->_hash;
     
     DOMStringImpl *key;
     
@@ -240,7 +244,7 @@ void AtomicString::remove(DOMStringImpl 
     numCollisions += _table[i] && equal(_table[i], r);
 #endif
     while ((key = _table[i])) {
-        if (equal(key, r))
+        if (key == r)
             break;
         i = (i + 1) & _tableSizeMask;
     }
Index: khtml/xml/dom_docimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_docimpl.cpp,v
retrieving revision 1.109
diff -u -p -r1.109 khtml/xml/dom_docimpl.cpp
--- khtml/xml/dom_docimpl.cpp	2004/02/02 17:47:30	1.109
+++ khtml/xml/dom_docimpl.cpp	2004/02/05 01:40:12
@@ -315,6 +315,10 @@ DocumentImpl::DocumentImpl(DOMImplementa
     m_cssTarget = 0;
     m_accessKeyDictValid = false;
     
+    resetLinkColor();
+    resetVisitedLinkColor();
+    resetActiveLinkColor();
+
     m_processingLoadEvent = false;
     m_startTime.restart();
 }
@@ -383,7 +387,21 @@ DocumentImpl::~DocumentImpl()
     }
 }
 
+void DocumentImpl::resetLinkColor()
+{
+    m_linkColor = QColor(0, 0, 238);
+}
+
+void DocumentImpl::resetVisitedLinkColor()
+{
+    m_visitedLinkColor = QColor(85, 26, 139);    
+}
 
+void DocumentImpl::resetActiveLinkColor()
+{
+    m_activeLinkColor.setNamedColor(QString("red"));
+}
+
 DocumentTypeImpl *DocumentImpl::doctype() const
 {
     return m_doctype;
@@ -2201,12 +2219,7 @@ void DocumentImpl::recalcStyleSelector()
                     sheet = 0;
             }
         }
-        else if (n->isHTMLElement() && n->id() == ID_BODY) {
-                // <BODY> element (doesn't contain styles as such but vlink="..." and friends
-                // are treated as style declarations)
-            sheet = static_cast<HTMLBodyElementImpl*>(n)->sheet();
-        }
-            
+
         if (sheet) {
             sheet->ref();
             m_styleSheets->styleSheets.append(sheet);
Index: khtml/xml/dom_docimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_docimpl.h,v
retrieving revision 1.53
diff -u -p -r1.53 khtml/xml/dom_docimpl.h
--- khtml/xml/dom_docimpl.h	2004/01/30 07:44:44	1.53
+++ khtml/xml/dom_docimpl.h	2004/02/05 01:40:12
@@ -61,7 +61,6 @@ class KWQAccObjectCache;
 namespace khtml {
     class CSSStyleSelector;
     class DocLoader;
-    class CSSStyleSelectorList;
     class RenderImage;
     class EditCommand;
 }
@@ -340,6 +339,16 @@ public:
     void setTextColor( QColor color ) { m_textColor = color; }
     QColor textColor() const { return m_textColor; }
 
+    const QColor& linkColor() const { return m_linkColor; }
+    const QColor& visitedLinkColor() const { return m_visitedLinkColor; }
+    const QColor& activeLinkColor() const { return m_activeLinkColor; }
+    void setLinkColor(const QColor& c) { m_linkColor = c; }
+    void setVisitedLinkColor(const QColor& c) { m_visitedLinkColor = c; }
+    void setActiveLinkColor(const QColor& c) { m_activeLinkColor = c; }
+    void resetLinkColor();
+    void resetVisitedLinkColor();
+    void resetActiveLinkColor();
+    
     // internal
     NodeImpl *findElement( Id id );
 
@@ -558,6 +567,10 @@ protected:
     LocalStyleRefs m_localStyleRefs; // references to inlined style elements
     QPtrList<RegisteredEventListener> m_windowEventListeners;
     QPtrList<NodeImpl> m_maintainsState;
+
+    QColor m_linkColor;
+    QColor m_visitedLinkColor;
+    QColor m_activeLinkColor;
 
     DOMString m_preferredStylesheetSet;
 
Index: khtml/xml/dom_elementimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_elementimpl.cpp,v
retrieving revision 1.34
diff -u -p -r1.34 khtml/xml/dom_elementimpl.cpp
--- khtml/xml/dom_elementimpl.cpp	2004/01/30 07:44:44	1.34
+++ khtml/xml/dom_elementimpl.cpp	2004/02/05 01:40:12
@@ -186,24 +186,16 @@ ElementImpl::ElementImpl(DocumentPtr *do
     : NodeBaseImpl(doc)
 {
     namedAttrMap = 0;
-    m_styleDecls = 0;
     m_prefix = 0;
 }
 
 ElementImpl::~ElementImpl()
 {
-    if(namedAttrMap) {
+    if (namedAttrMap) {
         namedAttrMap->detachFromElement();
         namedAttrMap->deref();
     }
 
-    if (m_styleDecls) {
-        m_styleDecls->setNode(0);
-        m_styleDecls->parent()->deref();
-        m_styleDecls->setParent(0);
-        m_styleDecls->deref();
-    }
-
     if (m_prefix)
         m_prefix->deref();
 }
@@ -228,14 +220,37 @@ unsigned short ElementImpl::nodeType() c
 {
     return Node::ELEMENT_NODE;
 }
+
+CSSStyleDeclarationImpl* ElementImpl::inlineStyleDecl() const
+{
+    return 0;
+}
+
+CSSStyleDeclarationImpl* ElementImpl::attributeStyleDecl() const
+{
+    return 0;
+}
+
+CSSStyleDeclarationImpl* ElementImpl::getInlineStyleDecl()
+{
+    return 0;
+}
 
-bool ElementImpl::matchesCSSClass(const AtomicString& c, bool caseSensitive) const
+CSSStyleDeclarationImpl* ElementImpl::additionalAttributeStyleDecl()
 {
-    // Class is not supported on random XML elements.  A language (e.g., HTML, SVG) should indicate
-    // support using a subclass override.
-    return false;
+    return 0;
 }
 
+const AtomicStringList* ElementImpl::getClassList() const
+{
+    return 0;
+}
+
+const AtomicString& ElementImpl::getIDAttribute() const
+{
+    return namedAttrMap ? namedAttrMap->id() : nullAtom;
+}
+
 const AtomicString& ElementImpl::getAttribute(NodeImpl::Id id) const
 {
     if (namedAttrMap) {
@@ -313,13 +328,9 @@ NodeImpl *ElementImpl::cloneNode(bool de
     if (!clone) return 0;
 
     // clone attributes
-    if(namedAttrMap)
+    if (namedAttrMap)
         *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
 
-    // clone individual style rules
-    if (m_styleDecls)
-        *(clone->styleRules()) = *m_styleDecls;
-
     if (deep)
         cloneChildNodes(clone);
     return clone;
@@ -542,16 +553,6 @@ bool ElementImpl::childTypeAllowed( unsi
     }
 }
 
-void ElementImpl::createDecl( )
-{
-    m_styleDecls = new CSSStyleDeclarationImpl(0);
-    m_styleDecls->ref();
-    m_styleDecls->setParent(getDocument()->elementSheet());
-    m_styleDecls->parent()->ref();
-    m_styleDecls->setNode(this);
-    m_styleDecls->setStrictParsing( !getDocument()->inCompatMode() );
-}
-
 void ElementImpl::dispatchAttrRemovalEvent(AttributeImpl *attr)
 {
     if (!getDocument()->hasListenerType(DocumentImpl::DOMATTRMODIFIED_LISTENER))
@@ -708,10 +709,6 @@ NodeImpl *XMLElementImpl::cloneNode ( bo
     // clone attributes
     if(namedAttrMap)
         *(static_cast<NamedAttrMapImpl*>(clone->attributes())) = *namedAttrMap;
-
-    // clone individual style rules
-    if (m_styleDecls)
-        *(clone->styleRules()) = *m_styleDecls;
 
     if (deep)
         cloneChildNodes(clone);
Index: khtml/xml/dom_elementimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_elementimpl.h,v
retrieving revision 1.21
diff -u -p -r1.21 khtml/xml/dom_elementimpl.h
--- khtml/xml/dom_elementimpl.h	2004/01/30 07:44:44	1.21
+++ khtml/xml/dom_elementimpl.h	2004/02/05 01:40:12
@@ -46,6 +46,7 @@ namespace DOM {
 class ElementImpl;
 class DocumentImpl;
 class NamedAttrMapImpl;
+class AtomicStringList;
 
 // this has no counterpart in DOM, purely internal
 // representation of the nodevalue of an Attr.
@@ -154,8 +155,8 @@ public:
     ~ElementImpl();
 
     // Used to quickly determine whether or not an element has a given CSS class.
-    virtual bool matchesCSSClass(const AtomicString& c, bool caseSensitive) const;
-    
+    virtual const AtomicStringList* getClassList() const;
+    const AtomicString& getIDAttribute() const;
     const AtomicString& getAttribute( NodeImpl::Id id ) const;
     const AtomicString& getAttribute(const DOMString& localName) const { return getAttributeNS(QString::null, localName); }
     const AtomicString& getAttributeNS(const DOMString &namespaceURI,
@@ -201,12 +202,12 @@ public:
     virtual bool childAllowed( NodeImpl *newChild );
     virtual bool childTypeAllowed( unsigned short type );
 
-    DOM::CSSStyleDeclarationImpl *styleRules() {
-      if (!m_styleDecls) createDecl();
-      return m_styleDecls;
-    }
+    virtual CSSStyleDeclarationImpl* inlineStyleDecl() const;
+    virtual CSSStyleDeclarationImpl* attributeStyleDecl() const;
+    virtual CSSStyleDeclarationImpl* getInlineStyleDecl();
+    
     // used by table cells to share style decls created by the enclosing table.
-    virtual DOM::CSSStyleDeclarationImpl* getAdditionalStyleDecls() { return 0; }
+    virtual CSSStyleDeclarationImpl* additionalAttributeStyleDecl();
     
     void dispatchAttrRemovalEvent(AttributeImpl *attr);
     void dispatchAttrAdditionEvent(AttributeImpl *attr);
@@ -226,7 +227,6 @@ public:
 #endif
 protected:
     virtual void createAttributeMap() const;
-    void createDecl();
     DOMString openTagStartToString() const;
 
 private:
@@ -234,8 +234,6 @@ private:
 
 protected: // member variables
     mutable NamedAttrMapImpl *namedAttrMap;
-
-    DOM::CSSStyleDeclarationImpl *m_styleDecls;
     DOMStringImpl *m_prefix;
 };
 
@@ -296,6 +294,9 @@ public:
 
     virtual bool isHTMLAttributeMap() const;
 
+    const AtomicString& id() const { return m_id; }
+    void setID(const AtomicString& _id) { m_id = _id; }
+    
 private:
     // this method is internal, does no error checking at all
     void addAttribute(AttributeImpl* newAttribute);
@@ -308,6 +309,7 @@ protected:
     ElementImpl *element;
     AttributeImpl **attrs;
     uint len;
+    AtomicString m_id;
 };
 
 }; //namespace
Index: khtml/xml/dom_stringimpl.cpp
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_stringimpl.cpp,v
retrieving revision 1.20
diff -u -p -r1.20 khtml/xml/dom_stringimpl.cpp
--- khtml/xml/dom_stringimpl.cpp	2004/01/30 07:44:44	1.20
+++ khtml/xml/dom_stringimpl.cpp	2004/02/05 01:40:12
@@ -44,6 +44,7 @@ DOMStringImpl* DOMStringImpl::empty()
 
 DOMStringImpl::DOMStringImpl(const QChar *str, unsigned int len) {
     _hash = 0;
+    _inTable = false;
     bool havestr = str && len;
     s = QT_ALLOC_QCHAR_VEC( havestr ? len : 1 );
     if(str && len) {
@@ -59,6 +60,7 @@ DOMStringImpl::DOMStringImpl(const QChar
 DOMStringImpl::DOMStringImpl(const char *str)
 {
     _hash = 0;
+    _inTable = false;
     if(str && *str)
     {
         l = strlen(str);
@@ -79,6 +81,7 @@ DOMStringImpl::DOMStringImpl(const char 
 DOMStringImpl::DOMStringImpl(const char *str, unsigned int len)
 {
     _hash = 0;
+    _inTable = false;
     l = len;
     if (!l || !str)
         return;
@@ -92,6 +95,7 @@ DOMStringImpl::DOMStringImpl(const char 
 
 DOMStringImpl::DOMStringImpl(const QChar &ch) {
     _hash = 0;
+    _inTable = false;
     s = QT_ALLOC_QCHAR_VEC( 1 );
     s[0] = ch;
     l = 1;
@@ -99,13 +103,15 @@ DOMStringImpl::DOMStringImpl(const QChar
 
 DOMStringImpl::~DOMStringImpl()
 {
-    if (_hash) AtomicString::remove(this);
-    if(s) QT_DELETE_QCHAR_VEC(s);
+    if (_inTable)
+        AtomicString::remove(this);
+    if (s)
+        QT_DELETE_QCHAR_VEC(s);
 }
 
 void DOMStringImpl::append(DOMStringImpl *str)
 {
-    assert(_hash == 0);
+    assert(!_inTable);
     if(str && str->l != 0)
     {
         int newlen = l+str->l;
@@ -120,7 +126,7 @@ void DOMStringImpl::append(DOMStringImpl
 
 void DOMStringImpl::insert(DOMStringImpl *str, uint pos)
 {
-    assert(_hash == 0);
+    assert(!_inTable);
     if(pos > l)
     {
         append(str);
@@ -141,7 +147,7 @@ void DOMStringImpl::insert(DOMStringImpl
 
 void DOMStringImpl::truncate(int len)
 {
-    assert(_hash == 0);
+    assert(!_inTable);
     if(len > (int)l) return;
 
     int nl = len < 1 ? 1 : len;
@@ -154,7 +160,7 @@ void DOMStringImpl::truncate(int len)
 
 void DOMStringImpl::remove(uint pos, int len)
 {
-    assert(_hash == 0);
+    assert(!_inTable);
     if(len <= 0) return;
     if(pos >= l ) return;
     if((unsigned)len > l - pos)
@@ -171,7 +177,7 @@ void DOMStringImpl::remove(uint pos, int
 
 DOMStringImpl *DOMStringImpl::split(uint pos)
 {
-    assert(_hash == 0);
+    assert(!_inTable);
     if( pos >=l ) return new DOMStringImpl();
 
     uint newLen = l-pos;
Index: khtml/xml/dom_stringimpl.h
===================================================================
RCS file: /local/home/cvs/Labyrinth/WebCore/khtml/xml/dom_stringimpl.h,v
retrieving revision 1.8
diff -u -p -r1.8 khtml/xml/dom_stringimpl.h
--- khtml/xml/dom_stringimpl.h	2004/01/28 21:19:39	1.8
+++ khtml/xml/dom_stringimpl.h	2004/02/05 01:40:12
@@ -37,10 +37,10 @@ class DOMStringImpl : public khtml::Shar
 {
 private:
     struct WithOneRef { };
-    DOMStringImpl(WithOneRef) { s = 0; l = 0; _hash = 0; ref(); }
+    DOMStringImpl(WithOneRef) { s = 0; l = 0; _hash = 0; _inTable = false; ref(); }
 
 protected:
-    DOMStringImpl() { s = 0, l = 0; _hash = 0; }
+    DOMStringImpl() { s = 0, l = 0; _hash = 0; _inTable = false; }
 public:
     DOMStringImpl(const QChar *str, unsigned int len);
     DOMStringImpl(const char *str);
@@ -87,6 +87,7 @@ public:
     unsigned int l;
     QChar *s;
     mutable unsigned _hash;
+    bool _inTable;
 };
 
 };
-------------- next part --------------






More information about the Khtml-devel mailing list