📄 dom_docimpl.cpp
字号:
}typedef const char* (*NameLookupFunction)(unsigned short id);typedef int (*IdLookupFunction)(const char *tagStr, int len);NodeImpl::Id DocumentImpl::getId( NodeImpl::IdType _type, DOMStringImpl* _nsURI, DOMStringImpl *_prefix, DOMStringImpl *_name, bool readonly, bool /*lookupHTML*/, int *pExceptioncode){ /*kdDebug() << "DocumentImpl::getId( type: " << _type << ", uri: " << DOMString(_nsURI).string() << ", prefix: " << DOMString(_prefix).string() << ", name: " << DOMString(_name).string() << ", readonly: " << readonly << ", lookupHTML: " << lookupHTML << ", exceptions: " << (pExceptioncode ? "yes" : "no") << " )" << endl;*/ if(!_name || !_name->l) return 0; IdNameMapping *map; IdLookupFunction lookup; switch (_type) { case NodeImpl::ElementId: map = m_elementMap; lookup = getTagID; break; case NodeImpl::AttributeId: map = m_attrMap; lookup = getAttrID; break; case NodeImpl::NamespaceId: if( !strcasecmp(_name, XHTML_NAMESPACE) ) return xhtmlNamespace; //### Id == 0 can't be used with (void*)int based QDicts... if( _name->l == 0) return noNamespace; map = m_namespaceMap; lookup= 0; break; default: return 0; } NodeImpl::Id id, nsid = 0; QConstString n(_name->s, _name->l); bool cs = true; // case sensitive if (_type != NodeImpl::NamespaceId) { if (_nsURI) nsid = getId( NodeImpl::NamespaceId, 0, 0, _nsURI, false, false, 0 ) << 16; // Each document maintains a mapping of tag name -> id for every tag name encountered // in the document. cs = (htmlMode() == XHtml) || (_nsURI && _type != NodeImpl::AttributeId); if (!nsid) { // First see if it's a HTML element name // xhtml is lower case - case sensitive, easy to implement if ( cs && (id = lookup(n.string().ascii(), _name->l)) ) return id; // compatibility: upper case - case insensitive if ( !cs && (id = lookup(n.string().lower().ascii(), _name->l )) ) return id; } } // Look in the names array for the name // compatibility mode has to lookup upper case QString name = cs ? n.string() : n.string().upper(); if (!_nsURI) { id = (NodeImpl::Id)(long) map->ids.find( name ); if (!id && _type != NodeImpl::NamespaceId) id = (NodeImpl::Id)(long) map->ids.find( "aliases: " + name ); } else { id = (NodeImpl::Id)(long) map->ids.find( name ); if (!readonly && id && _prefix && _prefix->l) { // we were called in registration mode... check if the alias exists QConstString px( _prefix->s, _prefix->l ); QString qn("aliases: " + (cs ? px.string() : px.string().upper()) + ":" + name); if (!map->ids.find( qn )) { map->ids.insert( qn, (void*)id ); } } } if (id) return nsid + id; // unknown if (readonly) return 0; if ( pExceptioncode && _type != NodeImpl::NamespaceId && !Element::khtmlValidQualifiedName(_name)) { *pExceptioncode = DOMException::INVALID_CHARACTER_ERR; return 0; } // Name not found, so let's add it NodeImpl::Id cid = map->count++ + map->idStart; map->names.insert( cid, _name ); _name->ref(); map->ids.insert( name, (void*)cid ); // and register an alias if needed for DOM1 methods compatibility if(_prefix && _prefix->l) { QConstString px( _prefix->s, _prefix->l ); QString qn("aliases: " + (cs ? px.string() : px.string().upper()) + ":" + name); if (!map->ids.find( qn )) { map->ids.insert( qn, (void*)cid ); } } if (map->ids.size() == map->ids.count() && map->ids.size() != khtml_MaxSeed) map->ids.resize( khtml::nextSeed(map->ids.count()) ); if (map->names.size() == map->names.count() && map->names.size() != khtml_MaxSeed) map->names.resize( khtml::nextSeed(map->names.count()) ); return nsid + cid; }NodeImpl::Id DocumentImpl::getId( NodeImpl::IdType _type, DOMStringImpl *_nodeName, bool readonly, bool lookupHTML, int *pExceptioncode){ return getId(_type, 0, 0, _nodeName, readonly, lookupHTML, pExceptioncode);}DOMString DocumentImpl::getName( NodeImpl::IdType _type, NodeImpl::Id _id ) const{ IdNameMapping *map; NameLookupFunction lookup; bool hasNS = (_id & NodeImpl_IdNSMask); switch (_type) { case NodeImpl::ElementId: map = m_elementMap; lookup = getTagName; break; case NodeImpl::AttributeId: map = m_attrMap; lookup = getAttrName; break; case NodeImpl::NamespaceId: if( _id == xhtmlNamespace ) return XHTML_NAMESPACE; if( _id == noNamespace ) return ""; map = m_namespaceMap; lookup = 0; break; default: return DOMString();; } _id = _id & NodeImpl_IdLocalMask; if (_id >= map->idStart) return map->names[_id]; else if (lookup) { // ### put them in a cache if (hasNS) return DOMString(lookup(_id)).lower(); else return lookup(_id); } else return DOMString();}// This method is called whenever a top-level stylesheet has finished loading.void DocumentImpl::styleSheetLoaded(){ // Make sure we knew this sheet was pending, and that our count isn't out of sync. assert(m_pendingStylesheets > 0); m_pendingStylesheets--; updateStyleSelector();}DOMString DocumentImpl::selectedStylesheetSet() const{ if (!view()) return DOMString(); return view()->part()->d->m_sheetUsed;}void DocumentImpl::setSelectedStylesheetSet(const DOMString& s){ // this code is evil if (view() && view()->part()->d->m_sheetUsed != s.string()) { view()->part()->d->m_sheetUsed = s.string(); updateStyleSelector(); }}void DocumentImpl::addStyleSheet(StyleSheetImpl *sheet, int *exceptioncode){ int excode = 0; if (!m_addedStyleSheets) { m_addedStyleSheets = new StyleSheetListImpl; m_addedStyleSheets->ref(); } m_addedStyleSheets->add(sheet); if (sheet->isCSSStyleSheet()) updateStyleSelector(); if (exceptioncode) *exceptioncode = excode;}void DocumentImpl::removeStyleSheet(StyleSheetImpl *sheet, int *exceptioncode){ int excode = 0; bool removed = false; bool is_css = sheet->isCSSStyleSheet(); if (m_addedStyleSheets) { bool in_main_list = !sheet->hasOneRef(); removed = m_addedStyleSheets->styleSheets.removeRef(sheet); sheet->deref(); if (m_addedStyleSheets->styleSheets.count() == 0) { bool reset = m_addedStyleSheets->hasOneRef(); m_addedStyleSheets->deref(); if (reset) m_addedStyleSheets = 0; } // remove from main list, too if (in_main_list) m_styleSheets->remove(sheet); } if (removed) { if (is_css) updateStyleSelector(); } else excode = DOMException::NOT_FOUND_ERR; if (exceptioncode) *exceptioncode = excode;}void DocumentImpl::updateStyleSelector(){// kdDebug() << "PENDING " << m_pendingStylesheets << endl; // Don't bother updating, since we haven't loaded all our style info yet. if (m_pendingStylesheets > 0) return; recalcStyleSelector(); recalcStyle(Force);#if 0 m_styleSelectorDirty = true;#endif if ( renderer() ) renderer()->setNeedsLayoutAndMinMaxRecalc();}void DocumentImpl::recalcStyleSelector(){ if ( !m_render || !attached() ) return; assert(m_pendingStylesheets==0); QPtrList<StyleSheetImpl> oldStyleSheets = m_styleSheets->styleSheets; m_styleSheets->styleSheets.clear(); QString sheetUsed = view() ? view()->part()->d->m_sheetUsed.replace("&&", "&") : QString(); bool autoselect = sheetUsed.isEmpty(); if (autoselect && !m_preferredStylesheetSet.isEmpty()) sheetUsed = m_preferredStylesheetSet.string(); NodeImpl *n; for (int i=0 ; i<2 ; i++) { m_availableSheets.clear(); m_availableSheets << i18n("Basic Page Style"); bool canResetSheet = false; for (n = this; n; n = n->traverseNextNode()) { StyleSheetImpl *sheet = 0; if (n->nodeType() == Node::PROCESSING_INSTRUCTION_NODE) { // Processing instruction (XML documents only) ProcessingInstructionImpl* pi = static_cast<ProcessingInstructionImpl*>(n); sheet = pi->sheet(); if (!sheet && !pi->localHref().isEmpty()) { // Processing instruction with reference to an element in this document - e.g. // <?xml-stylesheet href="#mystyle">, with the element // <foo id="mystyle">heading { color: red; }</foo> at some location in // the document ElementImpl* elem = getElementById(pi->localHref()); if (elem) { DOMString sheetText(""); NodeImpl *c; for (c = elem->firstChild(); c; c = c->nextSibling()) { if (c->nodeType() == Node::TEXT_NODE || c->nodeType() == Node::CDATA_SECTION_NODE) sheetText += c->nodeValue(); } CSSStyleSheetImpl *cssSheet = new CSSStyleSheetImpl(this); cssSheet->parseString(sheetText); pi->setStyleSheet(cssSheet); sheet = cssSheet; } } } else if (n->isHTMLElement() && ( n->id() == ID_LINK || n->id() == ID_STYLE) ) { QString title; if ( n->id() == ID_LINK ) { HTMLLinkElementImpl* l = static_cast<HTMLLinkElementImpl*>(n); if (l->isCSSStyleSheet()) { sheet = l->sheet(); if (sheet || l->isLoading() || l->isAlternate() ) title = l->getAttribute(ATTR_TITLE).string(); if ((autoselect || title != sheetUsed) && l->isDisabled()) { sheet = 0; } else if (!title.isEmpty() && !l->isAlternate() && sheetUsed.isEmpty()) { sheetUsed = title; l->setDisabled(false); } } } else { // <STYLE> element HTMLStyleElementImpl* s = static_cast<HTMLStyleElementImpl*>(n); if (!s->isLoading()) { sheet = s->sheet(); if (sheet) title = s->getAttribute(ATTR_TITLE).string(); } if (!title.isEmpty() && sheetUsed.isEmpty()) sheetUsed = title; } if ( !title.isEmpty() ) { if ( title != sheetUsed ) sheet = 0; // don't use it title = title.replace('&', "&&"); if ( !m_availableSheets.contains( title ) ) m_availableSheets.append( title ); } } 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); } // For HTML documents, stylesheets are not allowed within/after the <BODY> tag. So we // can stop searching here. if (isHTMLDocument() && n->id() == ID_BODY) { canResetSheet = !canResetSheet; break; } } // we're done if we don't select an alternative sheet // or we found the sheet we selected if (sheetUsed.isEmpty() || (!canResetSheet && tokenizer()) || m_availableSheets.contains(sheetUsed)) { break; } // the alternative sheet we used doesn't exist anymore // so try from scratch again if (view()) view()->part()->d->m_sheetUsed = QString::null; if (!m_preferredStylesheetSet.isEmpty() && !(sheetUsed == m_preferredStylesheetSet)) sheetUsed = m_preferredStylesheetSet.string(); else sheetUsed = QString::null; autoselect = true; } // Include programmatically added style sheets if (m_addedStyleSheets) { QPtrListIterator<StyleSheetImpl> it = m_addedStyleSheets->styleSheets; for (; *it; ++it) { if ((*it)->isCSSStyleSheet() && !(*it)->disabled()) m_styleSheets->add(*it); } } // De-reference all the stylesheets in the old list QPtrListIterator<StyleSheetImpl> it(oldStyleSheets); for (; it.current(); ++it) it.current()->deref(); // Create a new style selector delete m_styleSelector; QString usersheet = m_usersheet; if ( m_view && m_view->mediaType() == "print" ) usersheet += m_printSheet; m_styleSelector = new CSSStyleSelector( this, usersheet, m_styleSheets, m_url, !inCompatMode() ); m_styleSelectorDirty = false;}void DocumentImpl::setHoverNode(NodeImpl *newHoverNode){ NodeImpl* oldHoverNode = m_hoverNode; if (newHoverNode ) newHoverNode->ref(); m_hoverNode = newHoverNode; if ( oldHoverNode ) oldHoverNode->deref();}void DocumentImpl::setFocusNode(NodeImpl *newFocusNode){ // don't process focus changes while detaching if( !m_render ) return; // Make sure newFocusNode is actually in this document if (newFocusNode && (newFocusNode->getDocument() != this)) return; if (m_focusNode != newFocusNode) { NodeImpl *oldFocusNode = m_focusNode; // Set focus on the new node m_focusNode = newFocusNode; // Remove focus from the existing focus node (if any) if (oldFocusNode) { if (oldFocusNode->active()) oldFocusNode->setActive(false); oldFocusNode->setFocus(false); oldFocusNode->dispatchHTMLEvent(EventImpl::BLUR_EVENT,false,false); oldFocusNode->dispatchUIEvent(EventImpl::DOMFOCUSOUT_EVENT); if ((oldFocusNode == this) && oldFocusNode->hasOneRef()) { oldFocusNode->deref(); // deletes this return; } else { oldFocusNode->deref();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -