khtml Library API Documentation

css_base.cpp

00001 /* 00002 * This file is part of the DOM implementation for KDE. 00003 * 00004 * Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org) 00005 * 1999 Waldo Bastian (bastian@kde.org) 00006 * 2001 Andreas Schlapbach (schlpbch@iam.unibe.ch) 00007 * 2001-2003 Dirk Mueller (mueller@kde.org) 00008 * 2002 Apple Computer, Inc. 00009 * 2004 Allan Sandfeld Jensen (kde@carewolf.com) 00010 * 00011 * This library is free software; you can redistribute it and/or 00012 * modify it under the terms of the GNU Library General Public 00013 * License as published by the Free Software Foundation; either 00014 * version 2 of the License, or (at your option) any later version. 00015 * 00016 * This library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00019 * Library General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Library General Public License 00022 * along with this library; see the file COPYING.LIB. If not, write to 00023 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00024 * Boston, MA 02111-1307, USA. 00025 */ 00026 00027 //#define CSS_DEBUG 00028 00029 #include <assert.h> 00030 #include <kdebug.h> 00031 00032 #include "css_base.h" 00033 00034 #ifdef CSS_DEBUG 00035 #include "cssproperties.h" 00036 #endif 00037 00038 #include "css_stylesheetimpl.h" 00039 #include "xml/dom_docimpl.h" 00040 #include "misc/htmlhashes.h" 00041 #include "css_valueimpl.h" 00042 using namespace DOM; 00043 00044 void StyleBaseImpl::checkLoaded() const 00045 { 00046 if(m_parent) m_parent->checkLoaded(); 00047 } 00048 00049 StyleSheetImpl* StyleBaseImpl::stylesheet() 00050 { 00051 StyleBaseImpl* b = this; 00052 while(b && !b->isStyleSheet()) 00053 b = b->m_parent; 00054 return static_cast<StyleSheetImpl *>(b); 00055 } 00056 00057 KURL StyleBaseImpl::baseURL() 00058 { 00059 // try to find the style sheet. If found look for its url. 00060 // If it has none, look for the parentsheet, or the parentNode and 00061 // try to find out about their url 00062 00063 StyleSheetImpl *sheet = stylesheet(); 00064 00065 if(!sheet) return KURL(); 00066 00067 if(!sheet->href().isNull()) 00068 return KURL( sheet->href().string() ); 00069 00070 // find parent 00071 if(sheet->parent()) return sheet->parent()->baseURL(); 00072 00073 if(!sheet->ownerNode()) return KURL(); 00074 00075 return sheet->ownerNode()->getDocument()->baseURL(); 00076 } 00077 00078 void StyleBaseImpl::setParsedValue(int propId, const CSSValueImpl *parsedValue, 00079 bool important, bool nonCSSHint, QPtrList<CSSProperty> *propList) 00080 { 00081 QPtrListIterator<CSSProperty> propIt(*propList); 00082 propIt.toLast(); // just remove the top one - not sure what should happen if we have multiple instances of the property 00083 while (propIt.current() && 00084 ( propIt.current()->m_id != propId || propIt.current()->nonCSSHint != nonCSSHint || 00085 propIt.current()->m_bImportant != important) ) 00086 --propIt; 00087 if (propIt.current()) 00088 propList->removeRef(propIt.current()); 00089 00090 CSSProperty *prop = new CSSProperty(); 00091 prop->m_id = propId; 00092 prop->setValue((CSSValueImpl *) parsedValue); 00093 prop->m_bImportant = important; 00094 prop->nonCSSHint = nonCSSHint; 00095 00096 propList->append(prop); 00097 #ifdef CSS_DEBUG 00098 kdDebug( 6080 ) << "added property: " << getPropertyName(propId).string() 00099 // non implemented yet << ", value: " << parsedValue->cssText().string() 00100 << " important: " << prop->m_bImportant 00101 << " nonCSS: " << prop->nonCSSHint << endl; 00102 #endif 00103 } 00104 00105 // ------------------------------------------------------------------------------ 00106 00107 StyleListImpl::~StyleListImpl() 00108 { 00109 StyleBaseImpl *n; 00110 00111 if(!m_lstChildren) return; 00112 00113 for( n = m_lstChildren->first(); n != 0; n = m_lstChildren->next() ) 00114 { 00115 n->setParent(0); 00116 if( !n->refCount() ) delete n; 00117 } 00118 delete m_lstChildren; 00119 } 00120 00121 // -------------------------------------------------------------------------------- 00122 00123 void CSSSelector::print(void) 00124 { 00125 kdDebug( 6080 ) << "[Selector: tag = " << QString::number(tag,16) << ", attr = \"" << attr << "\", match = \"" << match 00126 << "\" value = \"" << value.string().latin1() << "\" relation = " << (int)relation 00127 << "]" << endl; 00128 if ( tagHistory ) 00129 tagHistory->print(); 00130 kdDebug( 6080 ) << " specificity = " << specificity() << endl; 00131 } 00132 00133 unsigned int CSSSelector::specificity() const 00134 { 00135 if ( nonCSSHint ) 00136 return 0; 00137 00138 int s = ((( tag & NodeImpl_IdLocalMask ) == 0xffff) ? 0 : 1); 00139 switch(match) 00140 { 00141 case Id: 00142 s += 0x10000; 00143 break; 00144 case Exact: 00145 case Set: 00146 case List: 00147 case Hyphen: 00148 case Pseudo: 00149 case Contain: 00150 case Begin: 00151 case End: 00152 s += 0x100; 00153 case None: 00154 break; 00155 } 00156 if(tagHistory) 00157 s += tagHistory->specificity(); 00158 // make sure it doesn't overflow 00159 return s & 0xffffff; 00160 } 00161 00162 void CSSSelector::extractPseudoType() const 00163 { 00164 if (match != Pseudo) 00165 return; 00166 _pseudoType = PseudoOther; 00167 if (!value.isEmpty()) { 00168 value = value.lower(); 00169 switch (value[0]) { 00170 case 'a': 00171 if (value == "active") 00172 _pseudoType = PseudoActive; 00173 else if (value == "after") 00174 _pseudoType = PseudoAfter; 00175 break; 00176 case 'b': 00177 if (value == "before") 00178 _pseudoType = PseudoBefore; 00179 break; 00180 case 'c': 00181 if (value == "checked") 00182 _pseudoType = PseudoChecked; 00183 else if (value == "contains(") 00184 _pseudoType = PseudoContains; 00185 break; 00186 case 'd': 00187 if (value == "disabled") 00188 _pseudoType = PseudoDisabled; 00189 break; 00190 case 'e': 00191 if (value == "empty") 00192 _pseudoType = PseudoEmpty; 00193 else if (value == "enabled") 00194 _pseudoType = PseudoEnabled; 00195 break; 00196 case 'f': 00197 if (value == "first-child") 00198 _pseudoType = PseudoFirstChild; 00199 else if (value == "first-letter") 00200 _pseudoType = PseudoFirstLetter; 00201 else if (value == "first-line") 00202 _pseudoType = PseudoFirstLine; 00203 else if (value == "first-of-type") 00204 _pseudoType = PseudoFirstOfType; 00205 else if (value == "focus") 00206 _pseudoType = PseudoFocus; 00207 break; 00208 case 'h': 00209 if (value == "hover") 00210 _pseudoType = PseudoHover; 00211 break; 00212 case 'i': 00213 if (value == "indeterminate") 00214 _pseudoType = PseudoIndeterminate; 00215 break; 00216 case 'l': 00217 if (value == "link") 00218 _pseudoType = PseudoLink; 00219 else if (value == "lang(") 00220 _pseudoType = PseudoLang; 00221 else if (value == "last-child") 00222 _pseudoType = PseudoLastChild; 00223 else if (value == "last-of-type") 00224 _pseudoType = PseudoLastOfType; 00225 break; 00226 case 'n': 00227 if (value == "not(") 00228 _pseudoType = PseudoNot; 00229 else if (value == "nth-child(") 00230 _pseudoType = PseudoNthChild; 00231 else if (value == "nth-last-child(") 00232 _pseudoType = PseudoNthLastChild; 00233 else if (value == "nth-of-type(") 00234 _pseudoType = PseudoNthOfType; 00235 else if (value == "nth-last-of-type(") 00236 _pseudoType = PseudoNthLastOfType; 00237 break; 00238 case 'o': 00239 if (value == "only-child") 00240 _pseudoType = PseudoOnlyChild; 00241 else if (value == "only-of-type") 00242 _pseudoType = PseudoOnlyOfType; 00243 break; 00244 case 'r': 00245 if (value == "root") 00246 _pseudoType = PseudoRoot; 00247 break; 00248 case 's': 00249 if (value == "selection") 00250 _pseudoType = PseudoSelection; 00251 break; 00252 case 't': 00253 if (value == "target") 00254 _pseudoType = PseudoTarget; 00255 break; 00256 case 'v': 00257 if (value == "visited") 00258 _pseudoType = PseudoVisited; 00259 break; 00260 } 00261 } 00262 00263 value = DOMString(); 00264 } 00265 00266 00267 bool CSSSelector::operator == ( const CSSSelector &other ) const 00268 { 00269 const CSSSelector *sel1 = this; 00270 const CSSSelector *sel2 = &other; 00271 00272 while ( sel1 && sel2 ) { 00273 //assert(sel1->_pseudoType != PseudoNotParsed); 00274 //assert(sel2->_pseudoType != PseudoNotParsed); 00275 if ( sel1->tag != sel2->tag || sel1->attr != sel2->attr || 00276 sel1->relation != sel2->relation || sel1->match != sel2->match || 00277 sel1->nonCSSHint != sel2->nonCSSHint || 00278 sel1->value != sel2->value || 00279 sel1->pseudoType() != sel2->pseudoType() || 00280 sel1->string_arg != sel2->string_arg) 00281 return false; 00282 sel1 = sel1->tagHistory; 00283 sel2 = sel2->tagHistory; 00284 } 00285 if ( sel1 || sel2 ) 00286 return false; 00287 return true; 00288 } 00289 00290 DOMString CSSSelector::selectorText() const 00291 { 00292 // #### fix namespace 00293 DOMString str; 00294 const CSSSelector* cs = this; 00295 if ( cs->tag == 0xffffffff && cs->attr == ATTR_ID && cs->match == CSSSelector::Id ) 00296 { 00297 str = "#"; 00298 str += cs->value; 00299 } 00300 else if ( cs->tag == 0xffffffff && cs->attr == ATTR_CLASS && cs->match == CSSSelector::List ) 00301 { 00302 str = "."; 00303 str += cs->value; 00304 } 00305 else if ( cs->tag == 0xffffffff && cs->match == CSSSelector::Pseudo ) 00306 { 00307 str = ":"; 00308 str += cs->value; 00309 } 00310 else 00311 { 00312 if ( cs->tag == 0xffffffff ) 00313 str = "*"; 00314 else if ( cs->tag != 0xffff ) 00315 str = getTagName( cs->tag ); 00316 if ( cs->attr == ATTR_ID && cs->match == CSSSelector::Id ) 00317 { 00318 str += "#"; 00319 str += cs->value; 00320 } 00321 else if ( cs->attr == ATTR_CLASS && cs->match == CSSSelector::List ) 00322 { 00323 str += "."; 00324 str += cs->value; 00325 } 00326 else if ( cs->match == CSSSelector::Pseudo ) 00327 { 00328 str += ":"; 00329 str += cs->value; 00330 } 00331 // optional attribute 00332 else if ( cs->attr ) { 00333 DOMString attrName = getAttrName( cs->attr ); 00334 str += "["; 00335 str += attrName; 00336 switch (cs->match) { 00337 case CSSSelector::Exact: 00338 str += "="; 00339 break; 00340 case CSSSelector::Set: 00341 str += " "; // ## correct? 00342 break; 00343 case CSSSelector::List: 00344 str += "~="; 00345 break; 00346 case CSSSelector::Hyphen: 00347 str += "|="; 00348 break; 00349 case CSSSelector::Begin: 00350 str += "^="; 00351 break; 00352 case CSSSelector::End: 00353 str += "$="; 00354 break; 00355 case CSSSelector::Contain: 00356 str += "*="; 00357 break; 00358 default: 00359 kdWarning(6080) << "Unhandled case in CSSStyleRuleImpl::selectorText : match=" << cs->match << endl; 00360 } 00361 str += "\""; 00362 str += cs->value; 00363 str += "\"]"; 00364 } 00365 } 00366 if ( cs->tagHistory ) { 00367 DOMString tagHistoryText = cs->tagHistory->selectorText(); 00368 if ( cs->relation == DirectAdjacent ) 00369 str = tagHistoryText + " + " + str; 00370 else if ( cs->relation == IndirectAdjacent ) 00371 str = tagHistoryText + " ~ " + str; 00372 else if ( cs->relation == Child ) 00373 str = tagHistoryText + " > " + str; 00374 else if ( cs->relation == SubSelector ) 00375 str += tagHistoryText; // the ":" is provided by selectorText() 00376 else // Descendant 00377 str = tagHistoryText + " " + str; 00378 } 00379 return str; 00380 } 00381 00382 // ----------------------------------------------------------------------------
KDE Logo
This file is part of the documentation for khtml Library Version 3.4.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Apr 12 23:31:20 2005 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003