#ifndef KHTML_NO_XBL
#include <kurl.h>
#include "xbl_protobinding.h"
#include "xbl_binding.h"
#include "xbl_docimpl.h"
#include "xbl_binding_manager.h"
#include "misc/loader.h"
using DOM::DOMString;
using DOM::ElementImpl;
using DOM::DocumentImpl;
using khtml::CachedXBLDocument;
namespace XBL
{
XBLBindingChain::XBLBindingChain(ElementImpl* elt, const DOMString& uri, bool isStyleChain)
:m_uri(uri), m_element(elt), m_previousChain(0), m_nextChain(0), m_isStyleChain(isStyleChain),
m_markedForDeath(false)
{
m_binding = new XBLBinding(this, uri);
}
XBLBindingChain::~XBLBindingChain()
{
delete m_binding;
delete m_nextChain;
}
XBLBindingChain* XBLBindingChain::firstStyleBindingChain()
{
if (m_isStyleChain)
return this;
if (m_nextChain)
return m_nextChain->firstStyleBindingChain();
return 0;
}
XBLBindingChain* XBLBindingChain::lastBindingChain()
{
if (m_nextChain)
return m_nextChain->lastBindingChain();
return this;
}
void XBLBindingChain::insertBindingChain(XBLBindingChain* bindingChain)
{
if (m_nextChain) {
m_nextChain->setPreviousBindingChain(bindingChain);
bindingChain->setNextBindingChain(m_nextChain);
}
if (bindingChain)
bindingChain->setPreviousBindingChain(this);
setNextBindingChain(bindingChain);
}
void XBLBindingChain::markForDeath()
{
m_markedForDeath = true;
if (m_nextChain && m_isStyleChain)
m_nextChain->markForDeath();
}
bool XBLBindingChain::loaded() const
{
if (m_binding && !m_binding->loaded())
return false;
if (m_nextChain)
return m_nextChain->loaded();
return true;
}
bool XBLBindingChain::hasStylesheets() const
{
if (m_binding && m_binding->hasStylesheets())
return true;
if (m_nextChain)
return m_nextChain->hasStylesheets();
return false;
}
void XBLBindingChain::failed()
{
delete m_binding;
m_binding = 0;
element()->getDocument()->bindingManager()->checkLoadState(element());
}
XBLBinding::XBLBinding(XBLBindingChain* ch, const DOMString& uri, XBLBinding* derivedBinding)
:m_chain(ch), m_xblDocument(0), m_prototype(0), m_previousBinding(0), m_nextBinding(0)
{
if (derivedBinding)
derivedBinding->setNextBinding(this);
setPreviousBinding(derivedBinding);
DOMString docURL = uri;
int hashIndex = uri.find('#');
if (hashIndex != -1) {
QString url = uri.string();
docURL = url.left(hashIndex);
if (int(url.length()) > hashIndex+1)
m_id = url.right(url.length()-hashIndex-1);
}
else
m_id = "_xbl_first_binding";
DocumentImpl* doc = chain()->element()->getDocument();
m_xblDocument = doc->docLoader()->requestXBLDocument(docURL);
if (m_xblDocument)
m_xblDocument->ref(this);
}
XBLBinding::~XBLBinding()
{
delete m_nextBinding;
if (m_xblDocument)
m_xblDocument->deref(this);
}
bool XBLBinding::loaded() const
{
if (!m_prototype)
return false;
if (m_nextBinding && !m_nextBinding->loaded())
return false;
return true;
}
void XBLBinding::setXBLDocument(const DOMString& url, XBLDocumentImpl* doc)
{
if (m_id == "_xbl_first_binding") {
}
m_prototype = doc->prototypeBinding(m_id);
if (!m_prototype)
return chain()->failed();
DOMString extends = m_prototype->element()->getAttribute("extends");
if (!extends.isEmpty()) {
new XBLBinding(chain(),
KURL(m_prototype->document()->baseURL(), extends.string()).url(),
this);
return;
}
chain()->element()->getDocument()->bindingManager()->checkLoadState(chain()->element());
}
}
#endif // KHTML_NO_XBL