2001-11-02 01:53:13 +00:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
|
|
|
* Version: NPL 1.1/GPL 2.0/LGPL 2.1
|
|
|
|
*
|
|
|
|
* The contents of this file are subject to the Netscape Public License
|
|
|
|
* Version 1.1 (the "License"); you may not use this file except in
|
|
|
|
* compliance with the License. You may obtain a copy of the License at
|
|
|
|
* http://www.mozilla.org/NPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
|
|
|
* for the specific language governing rights and limitations under the
|
|
|
|
* License.
|
|
|
|
*
|
|
|
|
* The Original Code is Mozilla Communicator client code.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is
|
|
|
|
* Netscape Communications Corporation.
|
|
|
|
* Portions created by the Initial Developer are Copyright (C) 1998
|
|
|
|
* the Initial Developer. All Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
2001-11-03 10:12:20 +00:00
|
|
|
* David Hyatt <hyatt@netscape.com> (Original Author)
|
2001-11-02 01:53:13 +00:00
|
|
|
*
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the terms of
|
|
|
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
|
|
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
|
|
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
|
|
|
* of those above. If you wish to allow use of your version of this file only
|
|
|
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
|
|
|
* use your version of this file under the terms of the NPL, indicate your
|
|
|
|
* decision by deleting the provisions above and replace them with the notice
|
|
|
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
|
|
|
* the provisions above, a recipient may use your version of this file under
|
|
|
|
* the terms of any one of the NPL, the GPL or the LGPL.
|
|
|
|
*
|
|
|
|
* ***** END LICENSE BLOCK ***** */
|
|
|
|
|
|
|
|
#include "nsXBLContentSink.h"
|
|
|
|
#include "nsIDocument.h"
|
|
|
|
#include "nsIBindingManager.h"
|
|
|
|
#include "nsIDOMNode.h"
|
|
|
|
#include "nsIParser.h"
|
|
|
|
#include "nsXBLAtoms.h"
|
|
|
|
#include "nsINameSpaceManager.h"
|
|
|
|
#include "nsHTMLAtoms.h"
|
|
|
|
#include "nsLayoutAtoms.h"
|
|
|
|
#include "nsHTMLTokens.h"
|
|
|
|
#include "nsIURI.h"
|
2001-11-02 09:29:33 +00:00
|
|
|
#include "nsTextFragment.h"
|
2001-11-03 10:12:20 +00:00
|
|
|
#include "nsXULElement.h"
|
|
|
|
#include "nsXULAtoms.h"
|
2001-11-13 04:09:56 +00:00
|
|
|
#include "nsXBLProtoImplProperty.h"
|
|
|
|
#include "nsXBLProtoImplMethod.h"
|
|
|
|
#include "nsXBLProtoImplField.h"
|
2002-08-06 12:55:44 +00:00
|
|
|
#include "nsIConsoleService.h"
|
|
|
|
#include "nsIScriptError.h"
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2001-11-02 01:53:13 +00:00
|
|
|
nsresult
|
|
|
|
NS_NewXBLContentSink(nsIXMLContentSink** aResult,
|
|
|
|
nsIDocument* aDoc,
|
|
|
|
nsIURI* aURL,
|
|
|
|
nsIWebShell* aWebShell)
|
|
|
|
{
|
2002-12-11 14:24:49 +00:00
|
|
|
NS_ENSURE_ARG_POINTER(aResult);
|
|
|
|
|
2001-11-02 01:53:13 +00:00
|
|
|
nsXBLContentSink* it;
|
|
|
|
NS_NEWXPCOM(it, nsXBLContentSink);
|
2002-12-11 14:24:49 +00:00
|
|
|
NS_ENSURE_TRUE(it, NS_ERROR_OUT_OF_MEMORY);
|
|
|
|
|
2001-11-02 01:53:13 +00:00
|
|
|
nsresult rv = it->Init(aDoc, aURL, aWebShell);
|
2002-12-11 14:24:49 +00:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
return CallQueryInterface(it, aResult);
|
2001-11-02 01:53:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsXBLContentSink::nsXBLContentSink()
|
|
|
|
{
|
|
|
|
mState = eXBL_InDocument;
|
|
|
|
mSecondaryState = eXBL_None;
|
|
|
|
mDocInfo = nsnull;
|
|
|
|
mIsChromeOrResource = PR_FALSE;
|
2001-11-13 04:09:56 +00:00
|
|
|
mImplementation = nsnull;
|
|
|
|
mImplMember = nsnull;
|
|
|
|
mProperty = nsnull;
|
|
|
|
mMethod = nsnull;
|
|
|
|
mField = nsnull;
|
2002-09-04 06:57:25 +00:00
|
|
|
mPrettyPrintXML = PR_FALSE;
|
2001-11-02 01:53:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsXBLContentSink::~nsXBLContentSink()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsXBLContentSink::Init(nsIDocument* aDoc,
|
|
|
|
nsIURI* aURL,
|
|
|
|
nsIWebShell* aContainer)
|
|
|
|
{
|
|
|
|
nsresult rv;
|
2002-03-27 06:19:14 +00:00
|
|
|
rv = nsXMLContentSink::Init(aDoc, aURL, aContainer, nsnull);
|
2001-11-02 01:53:13 +00:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2001-11-02 09:29:33 +00:00
|
|
|
nsresult
|
|
|
|
nsXBLContentSink::FlushText(PRBool aCreateTextNode,
|
|
|
|
PRBool* aDidFlush)
|
|
|
|
{
|
2001-11-14 08:17:19 +00:00
|
|
|
if (mTextLength == 0) {
|
|
|
|
if (aDidFlush)
|
|
|
|
*aDidFlush = PR_FALSE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-11-14 01:37:43 +00:00
|
|
|
const nsASingleFragmentString& text = Substring(mText, mText+mTextLength);
|
|
|
|
if (mState == eXBL_InHandlers) {
|
|
|
|
// Get the text and add it to the event handler.
|
|
|
|
if (mSecondaryState == eXBL_InHandler)
|
|
|
|
mHandler->AppendHandlerText(text);
|
2001-11-02 09:29:33 +00:00
|
|
|
mTextLength = 0;
|
|
|
|
if (aDidFlush)
|
|
|
|
*aDidFlush = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
else if (mState == eXBL_InImplementation) {
|
|
|
|
if (mSecondaryState == eXBL_InConstructor ||
|
|
|
|
mSecondaryState == eXBL_InDestructor) {
|
|
|
|
// Construct a handler for the constructor/destructor.
|
|
|
|
// XXXdwh This is just awful. These used to be handlers called
|
|
|
|
// BindingAttached and BindingDetached, and they're still implemented
|
|
|
|
// using handlers. At some point, we need to change these to just
|
|
|
|
// be special functions on the class instead.
|
|
|
|
nsCOMPtr<nsIXBLPrototypeHandler> handler;
|
|
|
|
if (mSecondaryState == eXBL_InConstructor)
|
|
|
|
mBinding->GetConstructor(getter_AddRefs(handler));
|
|
|
|
else
|
|
|
|
mBinding->GetDestructor(getter_AddRefs(handler));
|
|
|
|
|
|
|
|
// Get the text and add it to the constructor/destructor.
|
2001-11-14 01:37:43 +00:00
|
|
|
handler->AppendHandlerText(text);
|
2001-11-13 04:09:56 +00:00
|
|
|
}
|
|
|
|
else if (mSecondaryState == eXBL_InGetter ||
|
|
|
|
mSecondaryState == eXBL_InSetter) {
|
|
|
|
// Get the text and add it to the constructor/destructor.
|
2001-11-14 01:37:43 +00:00
|
|
|
if (mSecondaryState == eXBL_InGetter)
|
|
|
|
mProperty->AppendGetterText(text);
|
|
|
|
else
|
|
|
|
mProperty->AppendSetterText(text);
|
2001-11-13 04:09:56 +00:00
|
|
|
}
|
|
|
|
else if (mSecondaryState == eXBL_InBody) {
|
|
|
|
// Get the text and add it to the method
|
2001-11-14 01:37:43 +00:00
|
|
|
mMethod->AppendBodyText(text);
|
2001-11-13 04:09:56 +00:00
|
|
|
}
|
|
|
|
else if (mSecondaryState == eXBL_InField) {
|
|
|
|
// Get the text and add it to the method
|
2001-11-14 01:37:43 +00:00
|
|
|
mField->AppendFieldText(text);
|
|
|
|
}
|
|
|
|
mTextLength = 0;
|
|
|
|
if (aDidFlush)
|
|
|
|
*aDidFlush = PR_TRUE;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool isWS = PR_TRUE;
|
|
|
|
if (mTextLength > 0) {
|
|
|
|
const PRUnichar* cp = mText;
|
|
|
|
const PRUnichar* end = mText + mTextLength;
|
|
|
|
while (cp < end) {
|
|
|
|
PRUnichar ch = *cp++;
|
|
|
|
if (!XP_IS_SPACE(ch)) {
|
|
|
|
isWS = PR_FALSE;
|
|
|
|
break;
|
2001-11-02 01:53:13 +00:00
|
|
|
}
|
|
|
|
}
|
2001-11-14 01:37:43 +00:00
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
|
2001-11-14 01:37:43 +00:00
|
|
|
if (isWS && mTextLength > 0) {
|
|
|
|
mTextLength = 0;
|
|
|
|
if (aDidFlush)
|
|
|
|
*aDidFlush = PR_TRUE;
|
2001-11-02 01:53:13 +00:00
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2001-11-14 01:37:43 +00:00
|
|
|
return nsXMLContentSink::FlushText(aCreateTextNode, aDidFlush);
|
2001-11-02 01:53:13 +00:00
|
|
|
}
|
|
|
|
|
2002-08-06 12:55:44 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsXBLContentSink::ReportError(const PRUnichar* aErrorText,
|
|
|
|
const PRUnichar* aSourceText)
|
|
|
|
{
|
|
|
|
// XXX We should make sure the binding has no effect, but that it also
|
|
|
|
// gets destroyed properly without leaking. Perhaps we should even
|
|
|
|
// ensure that the content that was bound is displayed with no
|
|
|
|
// binding.
|
|
|
|
|
|
|
|
// Report the error to the error console.
|
|
|
|
nsCOMPtr<nsIConsoleService> consoleService =
|
|
|
|
do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
|
|
|
if (consoleService) {
|
|
|
|
// XXX It would be nice if the parser didn't pre-format it for us,
|
|
|
|
// because then we could create a instance of nsIScriptError and the
|
|
|
|
// error console would format this much more nicely for us.
|
|
|
|
// However, that would require duplicating even more code between
|
|
|
|
// the XML content sink and the XUL content sink.
|
|
|
|
|
|
|
|
consoleService->LogStringMessage(aErrorText);
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
// Report the error to stderr.
|
|
|
|
fprintf(stderr,
|
|
|
|
"\n%s\n%s\n\n",
|
|
|
|
NS_LossyConvertUCS2toASCII(aErrorText).get(),
|
|
|
|
NS_LossyConvertUCS2toASCII(aSourceText).get());
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// Most of what this does won't be too useful, but whatever...
|
|
|
|
return nsXMLContentSink::ReportError(aErrorText, aSourceText);
|
|
|
|
}
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsXBLContentSink::HandleStartElement(const PRUnichar *aName,
|
|
|
|
const PRUnichar **aAtts,
|
2002-01-09 18:15:36 +00:00
|
|
|
PRUint32 aAttsCount,
|
|
|
|
PRUint32 aIndex,
|
|
|
|
PRUint32 aLineNumber)
|
2001-11-03 10:12:20 +00:00
|
|
|
{
|
2002-01-09 01:37:50 +00:00
|
|
|
nsresult rv = nsXMLContentSink::HandleStartElement(aName,aAtts,aAttsCount,aIndex,aLineNumber);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (mState == eXBL_InBinding && !mBinding)
|
|
|
|
ConstructBinding();
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
return rv;
|
|
|
|
}
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsXBLContentSink::HandleEndElement(const PRUnichar *aName)
|
|
|
|
{
|
|
|
|
FlushText();
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (mState != eXBL_InDocument) {
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, tagAtom;
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
SplitXMLName(nsDependentString(aName), getter_AddRefs(nameSpacePrefix),
|
|
|
|
getter_AddRefs(tagAtom));
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
PRInt32 nameSpaceID = GetNameSpaceId(nameSpacePrefix);
|
|
|
|
if (nameSpaceID == kNameSpaceID_XBL) {
|
|
|
|
if (mState == eXBL_InHandlers) {
|
|
|
|
if (tagAtom == nsXBLAtoms::handlers) {
|
|
|
|
mState = eXBL_InBinding;
|
|
|
|
mHandler = nsnull;
|
|
|
|
}
|
|
|
|
else if (tagAtom == nsXBLAtoms::handler)
|
|
|
|
mSecondaryState = eXBL_None;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else if (mState == eXBL_InResources) {
|
|
|
|
if (tagAtom == nsXBLAtoms::resources)
|
|
|
|
mState = eXBL_InBinding;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
else if (mState == eXBL_InImplementation) {
|
|
|
|
if (tagAtom == nsXBLAtoms::implementation)
|
|
|
|
mState = eXBL_InBinding;
|
|
|
|
else if (tagAtom == nsXBLAtoms::property) {
|
|
|
|
mSecondaryState = eXBL_None;
|
|
|
|
mProperty = nsnull;
|
|
|
|
}
|
|
|
|
else if (tagAtom == nsXBLAtoms::method) {
|
|
|
|
mSecondaryState = eXBL_None;
|
|
|
|
mMethod = nsnull;
|
|
|
|
}
|
|
|
|
else if (tagAtom == nsXBLAtoms::field) {
|
|
|
|
mSecondaryState = eXBL_None;
|
|
|
|
mField = nsnull;
|
|
|
|
}
|
|
|
|
else if (tagAtom == nsXBLAtoms::constructor ||
|
|
|
|
tagAtom == nsXBLAtoms::destructor)
|
|
|
|
mSecondaryState = eXBL_None;
|
|
|
|
else if (tagAtom == nsXBLAtoms::getter ||
|
|
|
|
tagAtom == nsXBLAtoms::setter)
|
|
|
|
mSecondaryState = eXBL_InProperty;
|
|
|
|
else if (tagAtom == nsXBLAtoms::parameter ||
|
|
|
|
tagAtom == nsXBLAtoms::body)
|
|
|
|
mSecondaryState = eXBL_InMethod;
|
|
|
|
return NS_OK;
|
|
|
|
}
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
nsresult rv = nsXMLContentSink::HandleEndElement(aName);
|
|
|
|
if (NS_FAILED(rv))
|
|
|
|
return rv;
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (mState == eXBL_InImplementation && tagAtom == nsXBLAtoms::implementation)
|
|
|
|
mState = eXBL_InBinding;
|
|
|
|
else if (mState == eXBL_InBinding && tagAtom == nsXBLAtoms::binding) {
|
|
|
|
mState = eXBL_InDocument;
|
|
|
|
mBinding->Initialize();
|
|
|
|
mBinding = nsnull; // Clear our current binding ref.
|
2001-11-03 10:12:20 +00:00
|
|
|
}
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
return NS_OK;
|
2001-11-03 10:12:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
return nsXMLContentSink::HandleEndElement(aName);
|
2001-11-03 10:12:20 +00:00
|
|
|
}
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
NS_IMETHODIMP
|
|
|
|
nsXBLContentSink::HandleCDataSection(const PRUnichar *aData,
|
|
|
|
PRUint32 aLength)
|
|
|
|
{
|
|
|
|
if (mState == eXBL_InHandlers || mState == eXBL_InImplementation)
|
|
|
|
return AddText(aData, aLength);
|
|
|
|
return nsXMLContentSink::HandleCDataSection(aData, aLength);
|
|
|
|
}
|
|
|
|
|
|
|
|
PRBool
|
|
|
|
nsXBLContentSink::OnOpenContainer(const PRUnichar **aAtts,
|
|
|
|
PRUint32 aAttsCount,
|
|
|
|
PRInt32 aNameSpaceID,
|
|
|
|
nsIAtom* aTagName)
|
2001-11-03 10:12:20 +00:00
|
|
|
{
|
2002-01-09 01:37:50 +00:00
|
|
|
PRBool ret = PR_TRUE;
|
|
|
|
if (aNameSpaceID == kNameSpaceID_XBL) {
|
|
|
|
if (aTagName == nsXBLAtoms::bindings) {
|
|
|
|
NS_NewXBLDocumentInfo(mDocument, &mDocInfo);
|
|
|
|
if (!mDocInfo)
|
|
|
|
return NS_ERROR_FAILURE;
|
2001-11-05 06:45:04 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
nsCOMPtr<nsIBindingManager> bindingManager;
|
|
|
|
mDocument->GetBindingManager(getter_AddRefs(bindingManager));
|
|
|
|
bindingManager->PutXBLDocumentInfo(mDocInfo);
|
2001-11-05 06:45:04 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
nsCOMPtr<nsIURI> url;
|
|
|
|
mDocument->GetDocumentURL(getter_AddRefs(url));
|
|
|
|
|
|
|
|
PRBool isChrome = PR_FALSE;
|
|
|
|
PRBool isRes = PR_FALSE;
|
2001-11-03 10:12:20 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
url->SchemeIs("chrome", &isChrome);
|
|
|
|
url->SchemeIs("resource", &isRes);
|
|
|
|
mIsChromeOrResource = isChrome || isRes;
|
|
|
|
|
|
|
|
nsIXBLDocumentInfo* info = mDocInfo;
|
|
|
|
NS_RELEASE(info); // We keep a weak ref. We've created a cycle between doc/binding manager/doc info.
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::binding)
|
|
|
|
mState = eXBL_InBinding;
|
|
|
|
else if (aTagName == nsXBLAtoms::handlers) {
|
|
|
|
mState = eXBL_InHandlers;
|
|
|
|
ret = PR_FALSE; // The XML content sink should not do anything with <handlers>.
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::handler) {
|
|
|
|
mSecondaryState = eXBL_InHandler;
|
|
|
|
ConstructHandler(aAtts);
|
|
|
|
ret = PR_FALSE;
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::resources) {
|
|
|
|
mState = eXBL_InResources;
|
|
|
|
ret = PR_FALSE; // The XML content sink should ignore all <resources>.
|
|
|
|
}
|
|
|
|
else if (mState == eXBL_InResources) {
|
|
|
|
if (aTagName == nsXBLAtoms::stylesheet || aTagName == nsXBLAtoms::image)
|
|
|
|
ConstructResource(aAtts, aTagName);
|
|
|
|
ret = PR_FALSE; // The XML content sink should ignore everything within a <resources> block.
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::implementation) {
|
|
|
|
mState = eXBL_InImplementation;
|
|
|
|
ConstructImplementation(aAtts);
|
|
|
|
ret = PR_FALSE; // The XML content sink should ignore the <implementation>.
|
|
|
|
}
|
|
|
|
else if (mState == eXBL_InImplementation) {
|
|
|
|
if (aTagName == nsXBLAtoms::constructor) {
|
|
|
|
mSecondaryState = eXBL_InConstructor;
|
|
|
|
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
|
2002-06-19 00:43:46 +00:00
|
|
|
NS_NewXBLPrototypeHandler(nsnull, nsnull, nsnull, nsnull, nsnull,
|
2002-01-09 01:37:50 +00:00
|
|
|
nsnull, nsnull, nsnull, nsnull, nsnull,
|
|
|
|
getter_AddRefs(newHandler));
|
|
|
|
newHandler->SetEventName(nsXBLAtoms::constructor);
|
|
|
|
mBinding->SetConstructor(newHandler);
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::destructor) {
|
|
|
|
mSecondaryState = eXBL_InDestructor;
|
|
|
|
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
|
2002-06-19 00:43:46 +00:00
|
|
|
NS_NewXBLPrototypeHandler(nsnull, nsnull, nsnull, nsnull, nsnull,
|
2002-01-09 01:37:50 +00:00
|
|
|
nsnull, nsnull, nsnull, nsnull, nsnull,
|
|
|
|
getter_AddRefs(newHandler));
|
|
|
|
newHandler->SetEventName(nsXBLAtoms::destructor);
|
|
|
|
mBinding->SetDestructor(newHandler);
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::field) {
|
|
|
|
mSecondaryState = eXBL_InField;
|
|
|
|
ConstructField(aAtts);
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::property) {
|
|
|
|
mSecondaryState = eXBL_InProperty;
|
|
|
|
ConstructProperty(aAtts);
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::getter)
|
|
|
|
mSecondaryState = eXBL_InGetter;
|
|
|
|
else if (aTagName == nsXBLAtoms::setter)
|
|
|
|
mSecondaryState = eXBL_InSetter;
|
|
|
|
else if (aTagName == nsXBLAtoms::method) {
|
|
|
|
mSecondaryState = eXBL_InMethod;
|
|
|
|
ConstructMethod(aAtts);
|
|
|
|
}
|
|
|
|
else if (aTagName == nsXBLAtoms::parameter)
|
|
|
|
ConstructParameter(aAtts);
|
|
|
|
else if (aTagName == nsXBLAtoms::body)
|
|
|
|
mSecondaryState = eXBL_InBody;
|
2001-11-05 06:45:04 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
ret = PR_FALSE; // Ignore everything we encounter inside an <implementation> block.
|
|
|
|
}
|
2001-11-03 10:12:20 +00:00
|
|
|
}
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
return ret;
|
2001-11-03 10:12:20 +00:00
|
|
|
}
|
|
|
|
|
2001-11-02 01:53:13 +00:00
|
|
|
void
|
|
|
|
nsXBLContentSink::ConstructBinding()
|
|
|
|
{
|
|
|
|
nsCOMPtr<nsIContent> binding = getter_AddRefs(GetCurrentContent());
|
|
|
|
nsAutoString id;
|
|
|
|
binding->GetAttr(kNameSpaceID_None, nsHTMLAtoms::id, id);
|
|
|
|
nsCAutoString cid; cid.AssignWithConversion(id);
|
|
|
|
|
|
|
|
if (!cid.IsEmpty()) {
|
|
|
|
NS_NewXBLPrototypeBinding(cid, binding, mDocInfo, getter_AddRefs(mBinding));
|
|
|
|
mDocInfo->SetPrototypeBinding(cid, mBinding);
|
|
|
|
binding->UnsetAttr(kNameSpaceID_None, nsHTMLAtoms::id, PR_FALSE);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
|
2001-11-02 01:53:13 +00:00
|
|
|
void
|
2002-01-09 01:37:50 +00:00
|
|
|
nsXBLContentSink::ConstructHandler(const PRUnichar **aAtts)
|
2001-11-02 01:53:13 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
2002-01-09 01:37:50 +00:00
|
|
|
|
2002-06-19 00:43:46 +00:00
|
|
|
const PRUnichar* event = nsnull;
|
|
|
|
const PRUnichar* modifiers = nsnull;
|
|
|
|
const PRUnichar* button = nsnull;
|
|
|
|
const PRUnichar* clickcount = nsnull;
|
|
|
|
const PRUnichar* keycode = nsnull;
|
|
|
|
const PRUnichar* charcode = nsnull;
|
|
|
|
const PRUnichar* phase = nsnull;
|
|
|
|
const PRUnichar* command = nsnull;
|
|
|
|
const PRUnichar* action = nsnull;
|
|
|
|
const PRUnichar* preventdefault = nsnull;
|
2002-01-09 01:37:50 +00:00
|
|
|
|
|
|
|
for (; *aAtts; aAtts += 2) {
|
2001-11-02 01:53:13 +00:00
|
|
|
// Get upper-cased key
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
SplitXMLName(nsDependentString(aAtts[0]), getter_AddRefs(nameSpacePrefix),
|
2001-11-02 01:53:13 +00:00
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace) {
|
2001-11-02 01:53:13 +00:00
|
|
|
continue;
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
2001-11-02 01:53:13 +00:00
|
|
|
|
|
|
|
// Is this attribute one of the ones we care about?
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameAtom == nsXBLAtoms::event)
|
|
|
|
event = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::modifiers)
|
|
|
|
modifiers = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::button)
|
|
|
|
button = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::clickcount)
|
|
|
|
clickcount = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::keycode)
|
|
|
|
keycode = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::key || nameAtom == nsXBLAtoms::charcode)
|
|
|
|
charcode = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::phase)
|
|
|
|
phase = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::command)
|
|
|
|
command = aAtts[1];
|
|
|
|
else if (nameAtom == nsXBLAtoms::action)
|
|
|
|
action = aAtts[1];
|
2002-06-19 00:43:46 +00:00
|
|
|
else if (nameAtom == nsXBLAtoms::preventdefault)
|
|
|
|
preventdefault = aAtts[1];
|
2002-01-09 01:37:50 +00:00
|
|
|
else {
|
|
|
|
// Nope, it's some irrelevant attribute. Ignore it and move on.
|
|
|
|
}
|
2001-11-02 01:53:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (command && !mIsChromeOrResource)
|
|
|
|
// Make sure the XBL doc is chrome or resource if we have a command
|
|
|
|
// shorthand syntax.
|
|
|
|
return; // Don't even make this handler.
|
|
|
|
|
|
|
|
// All of our pointers are now filled in. Construct our handler with all of these
|
|
|
|
// parameters.
|
|
|
|
nsCOMPtr<nsIXBLPrototypeHandler> newHandler;
|
2002-01-09 21:50:08 +00:00
|
|
|
NS_NewXBLPrototypeHandler(event, phase, action, command,
|
|
|
|
keycode, charcode, modifiers, button,
|
2002-06-19 00:43:46 +00:00
|
|
|
clickcount, preventdefault,
|
|
|
|
getter_AddRefs(newHandler));
|
2001-11-02 01:53:13 +00:00
|
|
|
if (newHandler) {
|
|
|
|
// Add this handler to our chain of handlers.
|
|
|
|
if (mHandler)
|
|
|
|
mHandler->SetNextHandler(newHandler); // Already have a chain. Just append to the end.
|
|
|
|
else
|
|
|
|
mBinding->SetPrototypeHandlers(newHandler); // We're the first handler in the chain.
|
|
|
|
|
|
|
|
mHandler = newHandler; // Adjust our mHandler pointer to point to the new last handler in the chain.
|
|
|
|
}
|
|
|
|
}
|
2001-11-11 01:15:22 +00:00
|
|
|
|
|
|
|
void
|
2002-01-09 01:37:50 +00:00
|
|
|
nsXBLContentSink::ConstructResource(const PRUnichar **aAtts,
|
|
|
|
nsIAtom* aResourceType)
|
2001-11-11 01:15:22 +00:00
|
|
|
{
|
|
|
|
if (!mBinding)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
2002-01-09 01:37:50 +00:00
|
|
|
for (; *aAtts; aAtts += 2) {
|
2001-11-11 01:15:22 +00:00
|
|
|
// Get upper-cased key
|
2002-01-09 01:37:50 +00:00
|
|
|
const nsDependentString key(aAtts[0]);
|
2001-11-11 01:15:22 +00:00
|
|
|
|
|
|
|
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
|
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace) {
|
2001-11-11 01:15:22 +00:00
|
|
|
continue;
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
2001-11-11 01:15:22 +00:00
|
|
|
|
|
|
|
// Is this attribute one of the ones we care about?
|
|
|
|
if (key.Equals(NS_LITERAL_STRING("src"))) {
|
2002-01-09 01:37:50 +00:00
|
|
|
mBinding->AddResource(aResourceType, nsDependentString(aAtts[1]));
|
2001-11-11 01:15:22 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
|
|
|
|
void
|
2002-01-09 01:37:50 +00:00
|
|
|
nsXBLContentSink::ConstructImplementation(const PRUnichar **aAtts)
|
2001-11-13 04:09:56 +00:00
|
|
|
{
|
|
|
|
mImplementation = nsnull;
|
|
|
|
mImplMember = nsnull;
|
|
|
|
|
|
|
|
if (!mBinding)
|
|
|
|
return;
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
const PRUnichar* name = nsnull;
|
2001-11-13 04:09:56 +00:00
|
|
|
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
2002-01-09 01:37:50 +00:00
|
|
|
for (; *aAtts; aAtts +=2) {
|
2001-11-13 04:09:56 +00:00
|
|
|
// Get upper-cased key
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
SplitXMLName(nsDependentString(aAtts[0]), getter_AddRefs(nameSpacePrefix),
|
2001-11-13 04:09:56 +00:00
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace) {
|
2001-11-13 04:09:56 +00:00
|
|
|
continue;
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
|
|
|
|
// Is this attribute one of the ones we care about?
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameAtom == nsXBLAtoms::name) {
|
|
|
|
name = aAtts[1];
|
|
|
|
}
|
|
|
|
else if (nameAtom == nsXBLAtoms::implements) {
|
|
|
|
mBinding->ConstructInterfaceTable(nsDependentString(aAtts[1]));
|
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
}
|
|
|
|
|
2002-01-09 21:50:08 +00:00
|
|
|
NS_NewXBLProtoImpl(mBinding, name, &mImplementation);
|
2001-11-13 04:09:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-01-09 01:37:50 +00:00
|
|
|
nsXBLContentSink::ConstructField(const PRUnichar **aAtts)
|
2001-11-13 04:09:56 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
const PRUnichar* name = nsnull;
|
|
|
|
const PRUnichar* readonly = nsnull;
|
2001-11-13 04:09:56 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
for (; *aAtts; aAtts += 2) {
|
2001-11-13 04:09:56 +00:00
|
|
|
// Get upper-cased key
|
2002-01-09 01:37:50 +00:00
|
|
|
SplitXMLName(nsDependentString(aAtts[0]), getter_AddRefs(nameSpacePrefix),
|
2001-11-13 04:09:56 +00:00
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
|
|
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Is this attribute one of the ones we care about?
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameAtom == nsXBLAtoms::name) {
|
|
|
|
name = aAtts[1];
|
|
|
|
}
|
|
|
|
else if (nameAtom == nsXBLAtoms::readonly) {
|
|
|
|
readonly = aAtts[1];
|
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// All of our pointers are now filled in. Construct our field with all of these
|
|
|
|
// parameters.
|
2002-01-09 21:50:08 +00:00
|
|
|
mField = new nsXBLProtoImplField(name, readonly);
|
2001-11-13 04:09:56 +00:00
|
|
|
if (mField) {
|
|
|
|
// Add this member to our chain.
|
|
|
|
if (mImplMember)
|
|
|
|
mImplMember->SetNext(mField); // Already have a chain. Just append to the end.
|
|
|
|
else
|
|
|
|
mImplementation->SetMemberList(mField); // We're the first member in the chain.
|
|
|
|
|
|
|
|
mImplMember = mField; // Adjust our pointer to point to the new last member in the chain.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-01-09 01:37:50 +00:00
|
|
|
nsXBLContentSink::ConstructProperty(const PRUnichar **aAtts)
|
2001-11-13 04:09:56 +00:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
const PRUnichar* name = nsnull;
|
|
|
|
const PRUnichar* readonly = nsnull;
|
|
|
|
const PRUnichar* onget = nsnull;
|
|
|
|
const PRUnichar* onset = nsnull;
|
2001-11-13 04:09:56 +00:00
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
for (; *aAtts; aAtts += 2) {
|
2001-11-13 04:09:56 +00:00
|
|
|
// Get upper-cased key
|
2002-01-09 01:37:50 +00:00
|
|
|
SplitXMLName(nsDependentString(aAtts[0]), getter_AddRefs(nameSpacePrefix),
|
2001-11-13 04:09:56 +00:00
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace) {
|
2001-11-13 04:09:56 +00:00
|
|
|
continue;
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
|
|
|
|
// Is this attribute one of the ones we care about?
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameAtom == nsXBLAtoms::name) {
|
|
|
|
name = aAtts[1];
|
|
|
|
}
|
|
|
|
else if (nameAtom == nsXBLAtoms::readonly) {
|
|
|
|
readonly = aAtts[1];
|
|
|
|
}
|
|
|
|
else if (nameAtom == nsXBLAtoms::onget) {
|
|
|
|
onget = aAtts[1];
|
|
|
|
}
|
|
|
|
else if (nameAtom == nsXBLAtoms::onset) {
|
|
|
|
onset = aAtts[1];
|
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// All of our pointers are now filled in. Construct our property with all of these
|
|
|
|
// parameters.
|
2002-01-09 21:50:08 +00:00
|
|
|
mProperty = new nsXBLProtoImplProperty(name, onget, onset, readonly);
|
2001-11-13 04:09:56 +00:00
|
|
|
if (mProperty) {
|
|
|
|
// Add this member to our chain.
|
|
|
|
if (mImplMember)
|
|
|
|
mImplMember->SetNext(mProperty); // Already have a chain. Just append to the end.
|
|
|
|
else
|
|
|
|
mImplementation->SetMemberList(mProperty); // We're the first member in the chain.
|
|
|
|
|
|
|
|
mImplMember = mProperty; // Adjust our pointer to point to the new last member in the chain.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-01-09 01:37:50 +00:00
|
|
|
nsXBLContentSink::ConstructMethod(const PRUnichar **aAtts)
|
2001-11-13 04:09:56 +00:00
|
|
|
{
|
|
|
|
mMethod = nsnull;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
for(; *aAtts; aAtts += 2) {
|
2001-11-13 04:09:56 +00:00
|
|
|
// Get upper-cased key
|
2002-01-09 01:37:50 +00:00
|
|
|
SplitXMLName(nsDependentString(aAtts[0]), getter_AddRefs(nameSpacePrefix),
|
2001-11-13 04:09:56 +00:00
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace) {
|
2001-11-13 04:09:56 +00:00
|
|
|
continue;
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
|
|
|
|
// Is this attribute one of the ones we care about?
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameAtom == nsXBLAtoms::name) {
|
2002-01-09 21:50:08 +00:00
|
|
|
mMethod = new nsXBLProtoImplMethod(aAtts[1]);
|
2001-11-13 04:09:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mMethod) {
|
|
|
|
// Add this member to our chain.
|
|
|
|
if (mImplMember)
|
|
|
|
mImplMember->SetNext(mMethod); // Already have a chain. Just append to the end.
|
|
|
|
else
|
|
|
|
mImplementation->SetMemberList(mMethod); // We're the first member in the chain.
|
|
|
|
|
|
|
|
mImplMember = mMethod; // Adjust our pointer to point to the new last member in the chain.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2002-01-09 01:37:50 +00:00
|
|
|
nsXBLContentSink::ConstructParameter(const PRUnichar **aAtts)
|
2001-11-13 04:09:56 +00:00
|
|
|
{
|
|
|
|
if (!mMethod)
|
|
|
|
return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
for (; *aAtts; aAtts += 2) {
|
|
|
|
// Get upper-cased key
|
|
|
|
SplitXMLName(nsDependentString(aAtts[0]), getter_AddRefs(nameSpacePrefix),
|
2001-11-13 04:09:56 +00:00
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameSpacePrefix || nameAtom == nsLayoutAtoms::xmlnsNameSpace) {
|
2001-11-13 04:09:56 +00:00
|
|
|
continue;
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
2001-11-13 04:09:56 +00:00
|
|
|
|
|
|
|
// Is this attribute one of the ones we care about?
|
2002-01-09 01:37:50 +00:00
|
|
|
if (nameAtom == nsXBLAtoms::name) {
|
|
|
|
mMethod->AddParameter(nsDependentString(aAtts[1]));
|
2001-11-13 04:09:56 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-01-09 01:37:50 +00:00
|
|
|
|
|
|
|
nsresult
|
2002-12-02 23:24:57 +00:00
|
|
|
nsXBLContentSink::CreateElement(const PRUnichar** aAtts, PRUint32 aAttsCount,
|
|
|
|
nsINodeInfo* aNodeInfo, PRUint32 aLineNumber,
|
|
|
|
nsIContent** aResult, PRBool* aAppendContent)
|
2002-01-09 01:37:50 +00:00
|
|
|
{
|
2002-12-02 23:24:57 +00:00
|
|
|
if (!aNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
|
|
|
|
return nsXMLContentSink::CreateElement(aAtts, aAttsCount, aNodeInfo,
|
|
|
|
aLineNumber, aResult,
|
|
|
|
aAppendContent);
|
|
|
|
}
|
2002-01-09 01:37:50 +00:00
|
|
|
|
2002-12-02 23:24:57 +00:00
|
|
|
*aAppendContent = PR_TRUE;
|
|
|
|
nsXULPrototypeElement* prototype = new nsXULPrototypeElement();
|
|
|
|
if (!prototype)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
2002-01-09 01:37:50 +00:00
|
|
|
|
2002-12-02 23:24:57 +00:00
|
|
|
prototype->mNodeInfo = aNodeInfo;
|
2002-01-09 01:37:50 +00:00
|
|
|
|
2002-12-02 23:24:57 +00:00
|
|
|
// Reset the refcnt to 0. Normally XUL prototype elements get a refcnt of 1
|
|
|
|
// to represent ownership by the XUL prototype document. In our case we have
|
|
|
|
// no prototype document, and our initial ref count of 1 will come from being
|
|
|
|
// wrapped by a real XUL element in the Create call below.
|
|
|
|
prototype->mRefCnt = 0;
|
2002-01-09 01:37:50 +00:00
|
|
|
|
2002-12-02 23:24:57 +00:00
|
|
|
AddAttributesToXULPrototype(aAtts, aAttsCount, prototype);
|
|
|
|
|
|
|
|
// Following this function call, the prototype's ref count will be 1.
|
|
|
|
return nsXULElement::Create(prototype, mDocument, PR_FALSE, aResult);
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsXBLContentSink::AddAttributes(const PRUnichar** aAtts,
|
2002-12-02 23:24:57 +00:00
|
|
|
nsIContent* aContent)
|
2002-01-09 01:37:50 +00:00
|
|
|
{
|
|
|
|
if (aContent->IsContentOfType(nsIContent::eXUL))
|
|
|
|
return NS_OK; // Nothing to do, since the proto already has the attrs.
|
2002-12-02 23:24:57 +00:00
|
|
|
|
|
|
|
return nsXMLContentSink::AddAttributes(aAtts, aContent);
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsXBLContentSink::AddAttributesToXULPrototype(const PRUnichar **aAtts,
|
|
|
|
PRUint32 aAttsCount,
|
|
|
|
nsXULPrototypeElement* aElement)
|
|
|
|
{
|
|
|
|
// Add tag attributes to the element
|
|
|
|
nsresult rv;
|
|
|
|
|
|
|
|
// Create storage for the attributes
|
|
|
|
nsXULPrototypeAttribute* attrs = nsnull;
|
|
|
|
if (aAttsCount > 0) {
|
|
|
|
attrs = new nsXULPrototypeAttribute[aAttsCount];
|
|
|
|
if (!attrs)
|
|
|
|
return NS_ERROR_OUT_OF_MEMORY;
|
|
|
|
}
|
|
|
|
|
|
|
|
aElement->mAttributes = attrs;
|
|
|
|
aElement->mNumAttributes = aAttsCount;
|
|
|
|
|
|
|
|
// Copy the attributes into the prototype
|
|
|
|
nsCOMPtr<nsIAtom> nameSpacePrefix, nameAtom;
|
|
|
|
|
|
|
|
for (; *aAtts; aAtts += 2) {
|
|
|
|
const nsDependentString key(aAtts[0]);
|
|
|
|
|
|
|
|
SplitXMLName(key, getter_AddRefs(nameSpacePrefix),
|
|
|
|
getter_AddRefs(nameAtom));
|
|
|
|
|
|
|
|
PRInt32 nameSpaceID;
|
|
|
|
|
|
|
|
if (nameSpacePrefix)
|
|
|
|
nameSpaceID = GetNameSpaceId(nameSpacePrefix);
|
|
|
|
else {
|
|
|
|
if (nameAtom == nsLayoutAtoms::xmlnsNameSpace)
|
|
|
|
nameSpaceID = kNameSpaceID_XMLNS;
|
|
|
|
else
|
|
|
|
nameSpaceID = kNameSpaceID_None;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (kNameSpaceID_Unknown == nameSpaceID) {
|
|
|
|
nameSpaceID = kNameSpaceID_None;
|
2002-12-11 14:24:49 +00:00
|
|
|
nameAtom = do_GetAtom(key);
|
2002-01-09 01:37:50 +00:00
|
|
|
nameSpacePrefix = nsnull;
|
|
|
|
}
|
|
|
|
|
|
|
|
mNodeInfoManager->GetNodeInfo(nameAtom, nameSpacePrefix, nameSpaceID,
|
|
|
|
*getter_AddRefs(attrs->mNodeInfo));
|
|
|
|
|
|
|
|
attrs->mValue.SetValue(nsDependentString(aAtts[1]));
|
|
|
|
++attrs;
|
|
|
|
}
|
|
|
|
|
|
|
|
// XUL elements may require some additional work to compute
|
|
|
|
// derived information.
|
2002-11-29 23:44:07 +00:00
|
|
|
if (aElement->mNodeInfo->NamespaceEquals(kNameSpaceID_XUL)) {
|
2002-01-09 01:37:50 +00:00
|
|
|
nsAutoString value;
|
|
|
|
|
|
|
|
// Compute the element's class list if the element has a 'class' attribute.
|
|
|
|
rv = aElement->GetAttr(kNameSpaceID_None, nsXULAtoms::clazz, value);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
|
|
|
|
rv = nsClassList::ParseClasses(&aElement->mClassList, value);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Parse the element's 'style' attribute
|
|
|
|
rv = aElement->GetAttr(kNameSpaceID_None, nsHTMLAtoms::style, value);
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
|
|
|
|
if (rv == NS_CONTENT_ATTR_HAS_VALUE) {
|
|
|
|
if (!mCSSParser) {
|
2002-12-11 14:24:49 +00:00
|
|
|
mCSSParser = do_CreateInstance(kCSSParserCID, &rv);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2002-01-09 01:37:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rv = mCSSParser->ParseStyleAttribute(value, mDocumentURL,
|
|
|
|
getter_AddRefs(aElement->mInlineStyleRule));
|
|
|
|
|
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "unable to parse style rule");
|
|
|
|
if (NS_FAILED(rv)) return rv;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|