зеркало из https://github.com/mozilla/pjs.git
Merge of XForms code to the trunk. This has some rough edges still, like inputs not being treated as inline elements.
This commit is contained in:
Родитель
b53073c3c1
Коммит
7dd8608440
|
@ -0,0 +1 @@
|
|||
Makefile
|
|
@ -0,0 +1,88 @@
|
|||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla 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/MPL/
|
||||
#
|
||||
# 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.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# IBM Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2004
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Brian Ryner <bryner@brianryner.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = xforms
|
||||
LIBRARY_NAME = xforms
|
||||
IS_COMPONENT = 1
|
||||
EXPORT_LIBRARY = 1
|
||||
MODULE_NAME = xforms
|
||||
|
||||
REQUIRES = \
|
||||
xpcom \
|
||||
string \
|
||||
content \
|
||||
dom \
|
||||
widget \
|
||||
necko \
|
||||
websrvcs \
|
||||
xmlextras \
|
||||
docshell \
|
||||
mimetype \
|
||||
$(NULL)
|
||||
|
||||
CPPSRCS = \
|
||||
nsXFormsElementFactory.cpp \
|
||||
nsXFormsElement.cpp \
|
||||
nsXFormsControl.cpp \
|
||||
nsXFormsModelElement.cpp \
|
||||
nsXFormsInputElement.cpp \
|
||||
nsXFormsSubmissionElement.cpp \
|
||||
nsXFormsStubElement.cpp \
|
||||
nsXFormsInstanceElement.cpp \
|
||||
nsXFormsAtoms.cpp \
|
||||
nsXFormsModule.cpp \
|
||||
nsXFormsMDG.cpp \
|
||||
nsXFormsMDGEngine.cpp \
|
||||
nsXFormsMDGSet.cpp \
|
||||
nsXFormsXPathAnalyzer.cpp \
|
||||
nsXFormsXPathNode.cpp \
|
||||
nsXFormsXPathParser.cpp \
|
||||
nsXFormsXPathScanner.cpp \
|
||||
nsXFormsXPathXMLUtil.cpp \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DSO_LDOPTS = $(MOZ_COMPONENT_LIBS)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,72 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsAtoms.h"
|
||||
#include "nsMemory.h"
|
||||
|
||||
nsIAtom* nsXFormsAtoms::src;
|
||||
nsIAtom* nsXFormsAtoms::bind;
|
||||
nsIAtom* nsXFormsAtoms::type;
|
||||
nsIAtom* nsXFormsAtoms::readonly;
|
||||
nsIAtom* nsXFormsAtoms::required;
|
||||
nsIAtom* nsXFormsAtoms::relevant;
|
||||
nsIAtom* nsXFormsAtoms::calculate;
|
||||
nsIAtom* nsXFormsAtoms::constraint;
|
||||
nsIAtom* nsXFormsAtoms::p3ptype;
|
||||
nsIAtom* nsXFormsAtoms::modelListProperty;
|
||||
nsIAtom *nsXFormsAtoms::ref;
|
||||
|
||||
const nsStaticAtom nsXFormsAtoms::Atoms_info[] = {
|
||||
{ "src", &nsXFormsAtoms::src },
|
||||
{ "bind", &nsXFormsAtoms::bind },
|
||||
{ "type", &nsXFormsAtoms::type },
|
||||
{ "readonly", &nsXFormsAtoms::readonly },
|
||||
{ "required", &nsXFormsAtoms::required },
|
||||
{ "relevant", &nsXFormsAtoms::relevant },
|
||||
{ "calculate", &nsXFormsAtoms::calculate },
|
||||
{ "constraint", &nsXFormsAtoms::constraint },
|
||||
{ "p3ptype", &nsXFormsAtoms::p3ptype },
|
||||
{ "ModelListProperty", &nsXFormsAtoms::modelListProperty },
|
||||
{ "ref", &nsXFormsAtoms::ref },
|
||||
};
|
||||
|
||||
void
|
||||
nsXFormsAtoms::InitAtoms()
|
||||
{
|
||||
NS_RegisterStaticAtoms(Atoms_info, NS_ARRAY_LENGTH(Atoms_info));
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsStaticAtom.h"
|
||||
|
||||
class nsXFormsAtoms
|
||||
{
|
||||
public:
|
||||
static NS_HIDDEN_(nsIAtom *) src;
|
||||
static NS_HIDDEN_(nsIAtom *) bind;
|
||||
static NS_HIDDEN_(nsIAtom *) type;
|
||||
static NS_HIDDEN_(nsIAtom *) readonly;
|
||||
static NS_HIDDEN_(nsIAtom *) required;
|
||||
static NS_HIDDEN_(nsIAtom *) relevant;
|
||||
static NS_HIDDEN_(nsIAtom *) calculate;
|
||||
static NS_HIDDEN_(nsIAtom *) constraint;
|
||||
static NS_HIDDEN_(nsIAtom *) p3ptype;
|
||||
static NS_HIDDEN_(nsIAtom *) modelListProperty;
|
||||
static NS_HIDDEN_(nsIAtom *) ref;
|
||||
|
||||
static NS_HIDDEN_(void) InitAtoms();
|
||||
|
||||
private:
|
||||
static NS_HIDDEN_(const nsStaticAtom) Atoms_info[];
|
||||
};
|
|
@ -0,0 +1,67 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsElementFactory.h"
|
||||
#include "nsXFormsModelElement.h"
|
||||
#include "nsXFormsInstanceElement.h"
|
||||
#include "nsXFormsSubmissionElement.h"
|
||||
#include "nsXFormsStubElement.h"
|
||||
#include "nsString.h"
|
||||
|
||||
NS_HIDDEN_(nsresult) NS_NewXFormsInputElement(nsIXTFElement **aElement);
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsXFormsElementFactory, nsIXTFElementFactory)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsElementFactory::CreateElement(const nsAString& aTagName,
|
||||
nsIXTFElement **aElement)
|
||||
{
|
||||
if (aTagName.EqualsLiteral("model"))
|
||||
return NS_NewXFormsModelElement(aElement);
|
||||
if (aTagName.EqualsLiteral("instance"))
|
||||
return NS_NewXFormsInstanceElement(aElement);
|
||||
if (aTagName.EqualsLiteral("bind"))
|
||||
return NS_NewXFormsStubElement(aElement);
|
||||
if (aTagName.EqualsLiteral("input"))
|
||||
return NS_NewXFormsInputElement(aElement);
|
||||
if (aTagName.EqualsLiteral("submission"))
|
||||
return NS_NewXFormsSubmissionElement(aElement);
|
||||
|
||||
*aElement = nsnull;
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIXTFElementFactory.h"
|
||||
|
||||
#define NS_XFORMSELEMENTFACTORY_CID \
|
||||
{0xc068f682, 0x03b5, 0x4e96, {0x81, 0xe1, 0x60, 0x13, 0xf9, 0x12, 0x88, 0xb2}}
|
||||
|
||||
class nsXFormsElementFactory : public nsIXTFElementFactory
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIXTFELEMENTFACTORY
|
||||
};
|
|
@ -0,0 +1,401 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIXTFXMLVisual.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIXTFXMLVisualWrapper.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsXFormsControl.h"
|
||||
#include "nsISchema.h"
|
||||
#include "nsXFormsModelElement.h"
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsXFormsAtoms.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "nsIDOMXPathResult.h"
|
||||
#include "nsIDOMFocusListener.h"
|
||||
#include "nsIDOM3EventTarget.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
|
||||
static const nsIID sScriptingIIDs[] = {
|
||||
NS_IDOMELEMENT_IID,
|
||||
NS_IDOMEVENTTARGET_IID,
|
||||
NS_IDOM3NODE_IID
|
||||
};
|
||||
|
||||
class nsXFormsInputElement : public nsXFormsControl,
|
||||
public nsIXTFXMLVisual,
|
||||
public nsIDOMFocusListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIXTFXMLVISUAL
|
||||
NS_DECL_NSIXTFVISUAL
|
||||
NS_DECL_NSIXTFELEMENT
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
|
||||
|
||||
// nsIDOMFocusListener
|
||||
NS_IMETHOD Focus(nsIDOMEvent *aEvent);
|
||||
NS_IMETHOD Blur(nsIDOMEvent *aEvent);
|
||||
|
||||
// nsXFormsControl
|
||||
virtual NS_HIDDEN_(void) Refresh();
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> mInput;
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(nsXFormsInputElement)
|
||||
NS_IMPL_RELEASE(nsXFormsInputElement)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsXFormsInputElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFXMLVisual)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFXMLVisual)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
// nsIXTFXMLVisual
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::OnCreated(nsIXTFXMLVisualWrapper *aWrapper)
|
||||
{
|
||||
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_SET_ATTRIBUTE |
|
||||
nsIXTFElement::NOTIFY_ATTRIBUTE_SET);
|
||||
|
||||
mWrapper = aWrapper;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> node;
|
||||
mWrapper->GetElementNode(getter_AddRefs(node));
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
node->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
|
||||
nsCOMPtr<nsIDOMElement> inputElement;
|
||||
domDoc->CreateElementNS(NS_LITERAL_STRING(NS_NAMESPACE_XHTML),
|
||||
NS_LITERAL_STRING("input"),
|
||||
getter_AddRefs(inputElement));
|
||||
|
||||
mInput = do_QueryInterface(inputElement);
|
||||
NS_ENSURE_TRUE(mInput, NS_ERROR_FAILURE);
|
||||
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mInput);
|
||||
nsCOMPtr<nsIDOMEventGroup> group;
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(group));
|
||||
|
||||
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mInput);
|
||||
targ->AddGroupedEventListener(NS_LITERAL_STRING("blur"), this,
|
||||
PR_FALSE, group);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::GetVisualContent(nsIDOMElement **aElement)
|
||||
{
|
||||
NS_ADDREF(*aElement = mInput);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIXTFElement
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::OnDestroyed()
|
||||
{
|
||||
if (!mInput)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mInput);
|
||||
nsCOMPtr<nsIDOMEventGroup> group;
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(group));
|
||||
|
||||
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mInput);
|
||||
targ->RemoveGroupedEventListener(NS_LITERAL_STRING("blur"), this,
|
||||
PR_FALSE, group);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::GetElementType(PRUint32 *aType)
|
||||
{
|
||||
*aType = ELEMENT_TYPE_XML_VISUAL;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::GetIsAttributeHandler(PRBool *aIsHandler)
|
||||
{
|
||||
*aIsHandler = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
|
||||
{
|
||||
return CloneScriptingInterfaces(sScriptingIIDs,
|
||||
NS_ARRAY_LENGTH(sScriptingIIDs),
|
||||
aCount, aArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::WillChangeDocument(nsIDOMDocument *aNewDocument)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::DocumentChanged(nsIDOMDocument *aNewDocument)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::WillChangeParent(nsIDOMElement *aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::ParentChanged(nsIDOMElement *aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::WillInsertChild(nsIDOMNode *aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::WillAppendChild(nsIDOMNode *aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::ChildAppended(nsIDOMNode *aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::WillRemoveChild(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::ChildRemoved(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::WillSetAttribute(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
||||
nsCOMPtr<nsIDOMElement> bindElement;
|
||||
nsXFormsModelElement *model = GetModelAndBind(getter_AddRefs(bindElement));
|
||||
if (model)
|
||||
model->RemoveFormControl(this);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::AttributeSet(nsIAtom *aName, const nsAString &aValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::bind || aName == nsXFormsAtoms::ref) {
|
||||
Refresh();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::WillRemoveAttribute(nsIAtom *aName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::DoneAddingChildren()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDOMEventListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::HandleEvent(nsIDOMEvent *aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::Focus(nsIDOMEvent *aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInputElement::Blur(nsIDOMEvent *aEvent)
|
||||
{
|
||||
if (!mInput)
|
||||
return NS_OK;
|
||||
|
||||
nsRefPtr<nsXFormsModelElement> model;
|
||||
nsCOMPtr<nsIDOMElement> bindElement;
|
||||
nsCOMPtr<nsIDOMXPathResult> result =
|
||||
EvaluateBinding(nsIDOMXPathResult::FIRST_ORDERED_NODE_TYPE,
|
||||
getter_AddRefs(model), getter_AddRefs(bindElement));
|
||||
|
||||
if (!result)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMNode> singleNode;
|
||||
result->GetSingleNodeValue(getter_AddRefs(singleNode));
|
||||
|
||||
if (!singleNode)
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString value, type;
|
||||
mInput->GetType(type);
|
||||
if (type.EqualsLiteral("checkbox")) {
|
||||
PRBool checked;
|
||||
mInput->GetChecked(&checked);
|
||||
value.AssignASCII(checked ? "1" : "0", 1);
|
||||
} else {
|
||||
mInput->GetValue(value);
|
||||
}
|
||||
|
||||
PRUint16 nodeType = 0;
|
||||
singleNode->GetNodeType(&nodeType);
|
||||
|
||||
switch (nodeType) {
|
||||
case nsIDOMNode::ATTRIBUTE_NODE:
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
singleNode->SetNodeValue(value);
|
||||
break;
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
{
|
||||
nsCOMPtr<nsIDOM3Node> node = do_QueryInterface(singleNode);
|
||||
NS_ASSERTION(node, "DOM Nodes must support DOM3 interfaces");
|
||||
|
||||
node->SetTextContent(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// other methods
|
||||
|
||||
void
|
||||
nsXFormsInputElement::Refresh()
|
||||
{
|
||||
if (!mInput)
|
||||
return;
|
||||
|
||||
nsRefPtr<nsXFormsModelElement> model;
|
||||
nsCOMPtr<nsIDOMElement> bindElement;
|
||||
nsCOMPtr<nsIDOMXPathResult> result =
|
||||
EvaluateBinding(nsIDOMXPathResult::STRING_TYPE,
|
||||
getter_AddRefs(model), getter_AddRefs(bindElement));
|
||||
|
||||
if (model) {
|
||||
model->AddFormControl(this);
|
||||
|
||||
if (result) {
|
||||
nsAutoString nodeValue;
|
||||
result->GetStringValue(nodeValue);
|
||||
|
||||
nsCOMPtr<nsISchemaType> type = model->GetTypeForControl(this);
|
||||
nsCOMPtr<nsISchemaBuiltinType> biType = do_QueryInterface(type);
|
||||
PRUint16 typeValue = nsISchemaBuiltinType::BUILTIN_TYPE_STRING;
|
||||
|
||||
if (biType)
|
||||
biType->GetBuiltinType(&typeValue);
|
||||
|
||||
if (typeValue == nsISchemaBuiltinType::BUILTIN_TYPE_BOOLEAN) {
|
||||
mInput->SetAttribute(NS_LITERAL_STRING("type"),
|
||||
NS_LITERAL_STRING("checkbox"));
|
||||
|
||||
mInput->SetChecked(nodeValue.EqualsLiteral("true") ||
|
||||
nodeValue.EqualsLiteral("1"));
|
||||
} else {
|
||||
mInput->RemoveAttribute(NS_LITERAL_STRING("type"));
|
||||
mInput->SetValue(nodeValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsInputElement(nsIXTFElement **aResult)
|
||||
{
|
||||
*aResult = new nsXFormsInputElement();
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,431 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsInstanceElement.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsXFormsAtoms.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMXMLDocument.h"
|
||||
#include "nsIDOMDOMImplementation.h"
|
||||
|
||||
static const nsIID sScriptingIIDs[] = {
|
||||
NS_IDOMELEMENT_IID,
|
||||
NS_IDOMEVENTTARGET_IID,
|
||||
NS_IDOM3NODE_IID
|
||||
};
|
||||
|
||||
NS_IMPL_ADDREF(nsXFormsInstanceElement)
|
||||
NS_IMPL_RELEASE(nsXFormsInstanceElement)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsXFormsInstanceElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFGenericElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFPrivate)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFGenericElement)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::OnDestroyed()
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventReceiver> rec = do_QueryInterface(mDocument);
|
||||
if (rec)
|
||||
rec->RemoveEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener));
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::GetElementType(PRUint32 *aElementType)
|
||||
{
|
||||
*aElementType = nsIXTFElement::ELEMENT_TYPE_GENERIC_ELEMENT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::GetIsAttributeHandler(PRBool *aIsAttributeHandler)
|
||||
{
|
||||
*aIsAttributeHandler = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::GetScriptingInterfaces(PRUint32 *aCount,
|
||||
nsIID ***aArray)
|
||||
{
|
||||
return CloneScriptingInterfaces(sScriptingIIDs,
|
||||
NS_ARRAY_LENGTH(sScriptingIIDs),
|
||||
aCount, aArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::WillChangeDocument(nsIDOMDocument *aNewDocument)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::DocumentChanged(nsIDOMDocument *aNewDocument)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::WillChangeParent(nsIDOMElement *aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::ParentChanged(nsIDOMElement *aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::WillInsertChild(nsIDOMNode *aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::WillAppendChild(nsIDOMNode *aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::ChildAppended(nsIDOMNode *aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::WillRemoveChild(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::ChildRemoved(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::WillSetAttribute(nsIAtom *aName,
|
||||
const nsAString &aNewValue)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::AttributeSet(nsIAtom *aName,
|
||||
const nsAString &aNewValue)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::src) {
|
||||
// Note that this will fail if encountered during document construction,
|
||||
// because we won't be in the document yet, so CreateInstanceDocument
|
||||
// won't find a document to work with. That's ok, we'll fix things after
|
||||
// our children are appended and we're in the document (DoneAddingChildren)
|
||||
|
||||
LoadExternalInstance(aNewValue);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::WillRemoveAttribute(nsIAtom *aName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
if (aName == nsXFormsAtoms::src) {
|
||||
// We no longer have an external instance to use.
|
||||
// Reset our instance document to whatever inline content we have.
|
||||
return CloneInlineInstance();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::DoneAddingChildren()
|
||||
{
|
||||
// By the time this is called, we should be inserted in the document
|
||||
// and have all of our child elements, so this is our first opportunity
|
||||
// to create the instance document.
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
mWrapper->GetElementNode(getter_AddRefs(element));
|
||||
NS_ASSERTION(element, "no wrapper element");
|
||||
|
||||
nsAutoString src;
|
||||
element->GetAttribute(NS_LITERAL_STRING("src"), src);
|
||||
|
||||
if (src.IsEmpty()) {
|
||||
// If we don't have a linked external instance, use our inline data.
|
||||
CloneInlineInstance();
|
||||
} else {
|
||||
LoadExternalInstance(src);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
|
||||
{
|
||||
aWrapper->SetNotificationMask (nsIXTFElement::NOTIFY_PARENT_CHANGED |
|
||||
nsIXTFElement::NOTIFY_ATTRIBUTE_SET |
|
||||
nsIXTFElement::NOTIFY_ATTRIBUTE_REMOVED |
|
||||
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
|
||||
|
||||
mWrapper = aWrapper;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDOMLoadListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::Load(nsIDOMEvent *aEvent)
|
||||
{
|
||||
nsXFormsModelElement *model = GetModel();
|
||||
if (model)
|
||||
model->RemovePendingInstance();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::BeforeUnload(nsIDOMEvent *aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::Unload(nsIDOMEvent *aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::Abort(nsIDOMEvent *aEvent)
|
||||
{
|
||||
nsXFormsModelElement *model = GetModel();
|
||||
if (model) {
|
||||
model->RemovePendingInstance();
|
||||
model->DispatchEvent(eEvent_LinkException);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::Error(nsIDOMEvent *aEvent)
|
||||
{
|
||||
nsXFormsModelElement *model = GetModel();
|
||||
if (model) {
|
||||
model->RemovePendingInstance();
|
||||
model->DispatchEvent(eEvent_LinkException);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDOMEventListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::HandleEvent(nsIDOMEvent *aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIXTFPrivate
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsInstanceElement::GetInner(nsISupports **aInner)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInner);
|
||||
|
||||
NS_ADDREF(*aInner = NS_STATIC_CAST(nsIXTFGenericElement*, this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
// private methods
|
||||
|
||||
nsresult
|
||||
nsXFormsInstanceElement::CloneInlineInstance()
|
||||
{
|
||||
// Clear out our existing instance data
|
||||
nsresult rv = CreateInstanceDocument();
|
||||
if (NS_FAILED(rv))
|
||||
return rv; // don't warn, we might just not be in the document yet
|
||||
|
||||
// look for our first child element (skip over text nodes, etc.)
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
mWrapper->GetElementNode(getter_AddRefs(element));
|
||||
nsCOMPtr<nsIDOMNode> child, temp;
|
||||
|
||||
element->GetFirstChild(getter_AddRefs(child));
|
||||
while (child) {
|
||||
PRUint16 nodeType;
|
||||
child->GetNodeType(&nodeType);
|
||||
|
||||
if (nodeType == nsIDOMNode::ELEMENT_NODE)
|
||||
break;
|
||||
|
||||
temp.swap(child);
|
||||
temp->GetNextSibling(getter_AddRefs(child));
|
||||
}
|
||||
|
||||
if (child) {
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
rv = mDocument->ImportNode(child, PR_TRUE, getter_AddRefs(newNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> nodeReturn;
|
||||
rv = mDocument->AppendChild(newNode, getter_AddRefs(nodeReturn));
|
||||
NS_WARN_IF_FALSE(NS_SUCCEEDED(rv), "failed to append root instance node");
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsInstanceElement::LoadExternalInstance(const nsAString &aSrc)
|
||||
{
|
||||
// Clear out our existing instance data
|
||||
if (NS_FAILED(CreateInstanceDocument()))
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMEventReceiver> rec = do_QueryInterface(mDocument);
|
||||
rec->AddEventListenerByIID(this, NS_GET_IID(nsIDOMLoadListener));
|
||||
|
||||
nsCOMPtr<nsIDOMXMLDocument> xmlDoc = do_QueryInterface(mDocument);
|
||||
NS_ASSERTION(xmlDoc, "we created a document but it's not an XMLDocument?");
|
||||
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
mWrapper->GetElementNode(getter_AddRefs(element));
|
||||
|
||||
PRBool success;
|
||||
xmlDoc->Load(aSrc, &success);
|
||||
|
||||
nsXFormsModelElement *model = GetModel();
|
||||
if (model) {
|
||||
if (success)
|
||||
model->AddPendingInstance();
|
||||
else
|
||||
model->DispatchEvent(eEvent_LinkException);
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsInstanceElement::CreateInstanceDocument()
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
mWrapper->GetElementNode(getter_AddRefs(element));
|
||||
NS_ASSERTION(element, "no wrapper element");
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> doc;
|
||||
nsresult rv = element->GetOwnerDocument(getter_AddRefs(doc));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!doc) // could be we just aren't inserted yet, so don't warn
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
nsCOMPtr<nsIDOMDOMImplementation> domImpl;
|
||||
rv = doc->GetImplementation(getter_AddRefs(domImpl));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return domImpl->CreateDocument(EmptyString(), EmptyString(), nsnull,
|
||||
getter_AddRefs(mDocument));
|
||||
}
|
||||
|
||||
nsXFormsModelElement*
|
||||
nsXFormsInstanceElement::GetModel()
|
||||
{
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
mWrapper->GetElementNode(getter_AddRefs(element));
|
||||
NS_ASSERTION(element, "no wrapper element");
|
||||
|
||||
nsCOMPtr<nsIDOMNode> parentNode;
|
||||
element->GetParentNode(getter_AddRefs(parentNode));
|
||||
|
||||
nsCOMPtr<nsIXFormsModelElement> modelElt = do_QueryInterface(parentNode);
|
||||
if (!modelElt)
|
||||
return nsnull;
|
||||
|
||||
nsCOMPtr<nsIXTFPrivate> xtfPriv = do_QueryInterface(modelElt);
|
||||
NS_ENSURE_TRUE(xtfPriv, nsnull);
|
||||
|
||||
nsCOMPtr<nsISupports> modelInner;
|
||||
xtfPriv->GetInner(getter_AddRefs(modelInner));
|
||||
NS_ENSURE_TRUE(modelInner, nsnull);
|
||||
|
||||
nsISupports *isupp = NS_STATIC_CAST(nsISupports*, modelInner.get());
|
||||
return NS_STATIC_CAST(nsXFormsModelElement*,
|
||||
NS_STATIC_CAST(nsIXFormsModelElement*, isupp));
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewXFormsInstanceElement(nsIXTFElement **aResult)
|
||||
{
|
||||
*aResult = new nsXFormsInstanceElement();
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* nsXFormsInstanceElement implements the xforms <instance> element.
|
||||
* It creates an instance document by either cloning the inline instance data
|
||||
* or loading an external xml document given by the src attribute.
|
||||
*/
|
||||
|
||||
#ifndef nsXFormsInstanceElement_h_
|
||||
#define nsXFormsInstanceElement_h_
|
||||
|
||||
#include "nsIXTFGenericElement.h"
|
||||
#include "nsIXTFPrivate.h"
|
||||
#include "nsXFormsElement.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIXTFGenericElementWrapper.h"
|
||||
#include "nsIDOMLoadListener.h"
|
||||
#include "nsXFormsModelElement.h"
|
||||
|
||||
class nsXFormsInstanceElement : public nsXFormsElement,
|
||||
public nsIXTFGenericElement,
|
||||
public nsIXTFPrivate,
|
||||
public nsIDOMLoadListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIXTFELEMENT
|
||||
NS_DECL_NSIXTFGENERICELEMENT
|
||||
NS_DECL_NSIXTFPRIVATE
|
||||
|
||||
// nsIDOMEventListener
|
||||
NS_IMETHOD HandleEvent(nsIDOMEvent *aEvent);
|
||||
|
||||
// nsIDOMLoadListener
|
||||
NS_IMETHOD Load(nsIDOMEvent *aEvent);
|
||||
NS_IMETHOD BeforeUnload(nsIDOMEvent *aEvent);
|
||||
NS_IMETHOD Unload(nsIDOMEvent *aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent *aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent *aEvent);
|
||||
|
||||
NS_HIDDEN_(nsIDOMDocument*) GetDocument() { return mDocument; }
|
||||
|
||||
private:
|
||||
NS_HIDDEN_(nsresult) CloneInlineInstance();
|
||||
NS_HIDDEN_(void) LoadExternalInstance(const nsAString &aSrc);
|
||||
NS_HIDDEN_(nsresult) CreateInstanceDocument();
|
||||
NS_HIDDEN_(nsXFormsModelElement*) GetModel();
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> mDocument;
|
||||
nsCOMPtr<nsIXTFGenericElementWrapper> mWrapper;
|
||||
};
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsInstanceElement(nsIXTFElement **aResult);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,329 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsMDG.h"
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsIDOMText.h"
|
||||
#include "nsXFormsXPathNode.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsMDG)
|
||||
|
||||
nsXFormsMDG::nsXFormsMDG()
|
||||
: mEngine(this)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsMDG);
|
||||
}
|
||||
|
||||
nsXFormsMDG::~nsXFormsMDG()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXFormsMDG);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::Init()
|
||||
{
|
||||
return mEngine.Init();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::CreateNewChild(nsIDOMNode* aContextNode, const nsAString& aNodeValue,
|
||||
nsIDOMNode* aBeforeNode)
|
||||
{
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> document;
|
||||
rv = aContextNode->GetOwnerDocument(getter_AddRefs(document));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMText> textNode;
|
||||
rv = document->CreateTextNode(aNodeValue, getter_AddRefs(textNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> newNode;
|
||||
if (aBeforeNode) {
|
||||
rv = aContextNode->InsertBefore(textNode, aBeforeNode, getter_AddRefs(newNode));
|
||||
} else {
|
||||
rv = aContextNode->AppendChild(textNode, getter_AddRefs(newNode));
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::AddMIP(ModelItemPropName aType, nsIDOMXPathExpression* aExpression,
|
||||
nsXFormsMDGSet* aDeps, PRBool aDynFunc, nsIDOMNode* aContextNode,
|
||||
PRInt32 aContextPos, PRInt32 aContextSize)
|
||||
{
|
||||
NS_ENSURE_ARG(aExpression);
|
||||
NS_ENSURE_ARG(aContextNode);
|
||||
|
||||
return mEngine.Insert(aContextNode, aExpression, aDeps, aDynFunc, aContextPos, aContextSize, aType);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::MarkNodeAsChanged(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.MarkNode(aContextNode);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::Recalculate(nsXFormsMDGSet& aChangedNodes)
|
||||
{
|
||||
return mEngine.Calculate(aChangedNodes);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::Rebuild()
|
||||
{
|
||||
return mEngine.Rebuild();
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDG::ClearDispatchFlags()
|
||||
{
|
||||
mEngine.ClearDispatchFlags();
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDG::Clear() {
|
||||
mEngine.Clear();
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::GetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
|
||||
PRUint16 nodeType;
|
||||
rv = aContextNode->GetNodeType(&nodeType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
switch(nodeType) {
|
||||
case nsIDOMNode::ATTRIBUTE_NODE:
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
case nsIDOMNode::CDATA_SECTION_NODE:
|
||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
|
||||
case nsIDOMNode::COMMENT_NODE:
|
||||
rv = aContextNode->GetNodeValue(aNodeValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
break;
|
||||
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
rv = aContextNode->GetFirstChild(getter_AddRefs(childNode));
|
||||
if (NS_FAILED(rv) || !childNode) {
|
||||
// No child
|
||||
aNodeValue.Truncate(0);
|
||||
} else {
|
||||
PRUint16 childType;
|
||||
rv = childNode->GetNodeType(&childType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if ( childType == nsIDOMNode::TEXT_NODE
|
||||
|| childType == nsIDOMNode::CDATA_SECTION_NODE) {
|
||||
rv = childNode->GetNodeValue(aNodeValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
// Not a text child
|
||||
aNodeValue.Truncate(0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Asked for a node which cannot have a text child
|
||||
// TODO: Should return more specific error?
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDG::SetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue, PRBool aMarkNode)
|
||||
{
|
||||
if (IsReadonly(aContextNode)) {
|
||||
// TODO: Better feedback for readonly nodes?
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMNode> childNode;
|
||||
PRUint16 nodeType;
|
||||
rv = aContextNode->GetNodeType(&nodeType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
switch(nodeType) {
|
||||
case nsIDOMNode::ATTRIBUTE_NODE:
|
||||
case nsIDOMNode::TEXT_NODE:
|
||||
case nsIDOMNode::CDATA_SECTION_NODE:
|
||||
case nsIDOMNode::PROCESSING_INSTRUCTION_NODE:
|
||||
case nsIDOMNode::COMMENT_NODE:
|
||||
// TODO: Check existing value, and ignore if same??
|
||||
rv = aContextNode->SetNodeValue(aNodeValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
break;
|
||||
|
||||
case nsIDOMNode::ELEMENT_NODE:
|
||||
rv = aContextNode->GetFirstChild(getter_AddRefs(childNode));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!childNode) {
|
||||
rv = CreateNewChild(aContextNode, aNodeValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
PRUint16 childType;
|
||||
rv = childNode->GetNodeType(&childType);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if ( childType == nsIDOMNode::TEXT_NODE
|
||||
|| childType == nsIDOMNode::CDATA_SECTION_NODE) {
|
||||
rv = childNode->SetNodeValue(aNodeValue);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
} else {
|
||||
// Not a text child, create a new one
|
||||
rv = CreateNewChild(aContextNode, aNodeValue, childNode);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// Unsupported nodeType
|
||||
// TODO: Should return more specific error?
|
||||
return NS_ERROR_ILLEGAL_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
// NB: Never reached for Readonly nodes.
|
||||
if (aMarkNode) {
|
||||
MarkNodeAsChanged(aContextNode);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
/**********************************************/
|
||||
/* Bit test functions */
|
||||
/**********************************************/
|
||||
PRBool
|
||||
nsXFormsMDG::IsValid(nsIDOMNode* aContextNode)
|
||||
{
|
||||
|
||||
PRBool valid = mEngine.Test(aContextNode, MDG_FLAG_CONSTRAINT);
|
||||
if (valid) {
|
||||
// TODO: needs Schema support
|
||||
// valid = mSchemaHandler->ValidateNode(aContextNode);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::IsConstraint(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.Test(aContextNode, MDG_FLAG_CONSTRAINT);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::ShouldDispatchValid(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_VALID_CHANGED);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::IsReadonly(nsIDOMNode* aContextNode)
|
||||
{
|
||||
PRBool valid;
|
||||
if ( mEngine.Test(aContextNode, MDG_FLAG_READONLY)
|
||||
|| mEngine.Test(aContextNode, MDG_FLAG_INHERITED_READONLY)) {
|
||||
valid = PR_TRUE;
|
||||
} else {
|
||||
valid = PR_FALSE;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::ShouldDispatchReadonly(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_READONLY_CHANGED);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::IsRelevant(nsIDOMNode* aContextNode)
|
||||
{
|
||||
PRBool valid;
|
||||
if ( mEngine.Test(aContextNode, MDG_FLAG_RELEVANT)
|
||||
&& mEngine.Test(aContextNode, MDG_FLAG_INHERITED_RELEVANT)) {
|
||||
valid = PR_TRUE;
|
||||
} else {
|
||||
valid = PR_FALSE;
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::ShouldDispatchRelevant(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_RELEVANT_CHANGED);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::IsRequired(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.Test(aContextNode, MDG_FLAG_REQUIRED);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::ShouldDispatchRequired(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_REQUIRED_CHANGED);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDG::ShouldDispatchValueChanged(nsIDOMNode* aContextNode)
|
||||
{
|
||||
return mEngine.Test(aContextNode, MDG_FLAG_DISPATCH_VALUE_CHANGED);
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsString.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsIDOMXPathExpression.h"
|
||||
#include "nsXFormsMDGEngine.h"
|
||||
|
||||
/**
|
||||
* Class nsXFormsMDG.
|
||||
*
|
||||
* This a wrapper of the more low-level nsXFormsMDGEngine. It handles all the Multi
|
||||
* Dependency Graph (MDG) functions for the Mozilla XForms implementation.
|
||||
*/
|
||||
class nsXFormsMDG {
|
||||
protected:
|
||||
/**
|
||||
* The MDG engine used.
|
||||
*/
|
||||
nsXFormsMDGEngine mEngine;
|
||||
|
||||
/**
|
||||
* Inserts a new text child for aContextNode.
|
||||
*
|
||||
* @param aContextNode The node to create a child for
|
||||
* @param aNodeValue The value of the new node
|
||||
* @param aBeforeNode If non-null, insert new node before this node
|
||||
*/
|
||||
nsresult CreateNewChild(nsIDOMNode* aContextNode, const nsAString& aNodeValue, nsIDOMNode* aBeforeNode = nsnull);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor. Be sure to call Init() before using the object.
|
||||
*/
|
||||
nsXFormsMDG();
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
~nsXFormsMDG();
|
||||
|
||||
/**
|
||||
* Initializes internal objects. If it fails, the object is unusable.
|
||||
*/
|
||||
nsresult Init();
|
||||
|
||||
/**
|
||||
* Insert new MIP (Model Item Property) into graph.
|
||||
*
|
||||
* @param aType The type of MIP
|
||||
* @param aExpression The XPath expression
|
||||
* @param aDeps Set of nodes expression depends on
|
||||
* @param aDynFunc True if expression uses dynamic functions
|
||||
* @param aContextNode The context node for aExpression
|
||||
* @param aContextPos The context positions of aExpression
|
||||
* @param aContextSize The context size for aExpression
|
||||
*/
|
||||
nsresult AddMIP(ModelItemPropName aType, nsIDOMXPathExpression* aExpression,
|
||||
nsXFormsMDGSet* aDeps, PRBool aDynFunc,
|
||||
nsIDOMNode* aContextNode,
|
||||
PRInt32 aContextPos, PRInt32 aContextSize);
|
||||
|
||||
/**
|
||||
* Recalculate the MDG.
|
||||
*
|
||||
* @param aChangedNodes Returns the nodes that was changed during recalculation.
|
||||
*/
|
||||
nsresult Recalculate(nsXFormsMDGSet& aChangedNodes);
|
||||
|
||||
/**
|
||||
* Rebuilds the MDG.
|
||||
*/
|
||||
nsresult Rebuild();
|
||||
|
||||
/**
|
||||
* Clears all information in the MDG.
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Clears all Dispatch flags.
|
||||
*/
|
||||
void ClearDispatchFlags();
|
||||
|
||||
/**
|
||||
* Mark a node as changed.
|
||||
*
|
||||
* @param aContextNode The node to be marked.
|
||||
*/
|
||||
nsresult MarkNodeAsChanged(nsIDOMNode* aContextNode);
|
||||
|
||||
/**
|
||||
* Set the value of a node. (used by nsXFormsMDG)
|
||||
|
||||
* @param aContextNode The node to set the value for
|
||||
* @param aNodeValue The value
|
||||
* @param aMarkNode Mark node as changed?
|
||||
*/
|
||||
nsresult SetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue, PRBool aMarkNode = PR_FALSE);
|
||||
|
||||
/**
|
||||
* Get the value of a node. (used by nsXFormsMDG)
|
||||
|
||||
* @param aContextNode The node to get the value for
|
||||
* @param aNodeValue The value of the node
|
||||
*/
|
||||
nsresult GetNodeValue(nsIDOMNode* aContextNode, nsAString& aNodeValue);
|
||||
|
||||
PRBool IsConstraint(nsIDOMNode* aContextNode);
|
||||
PRBool IsValid(nsIDOMNode* aContextNode);
|
||||
PRBool ShouldDispatchValid(nsIDOMNode* aContextNode);
|
||||
PRBool IsReadonly(nsIDOMNode* aContextNode);
|
||||
PRBool ShouldDispatchReadonly(nsIDOMNode* aContextNode);
|
||||
PRBool IsRelevant(nsIDOMNode* aContextNode);
|
||||
PRBool ShouldDispatchRelevant(nsIDOMNode* aContextNode);
|
||||
PRBool IsRequired(nsIDOMNode* aContextNode);
|
||||
PRBool ShouldDispatchRequired(nsIDOMNode* aContextNode);
|
||||
PRBool ShouldDispatchValueChanged(nsIDOMNode* aContextNode);
|
||||
};
|
|
@ -0,0 +1,781 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsMDGEngine.h"
|
||||
#include "nsXFormsMDG.h"
|
||||
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsIDOMXPathExpression.h"
|
||||
#include "nsIDOMXPathResult.h"
|
||||
#include "nsDeque.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
// #define DEBUG_XF_MDG
|
||||
#endif
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* --------- nsXFormsMDGNode ---------- */
|
||||
/* ------------------------------------ */
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsMDGNode)
|
||||
|
||||
nsXFormsMDGNode::nsXFormsMDGNode(nsIDOMNode* aNode, const ModelItemPropName aType)
|
||||
: mDirty (PR_TRUE), mHasExpr(PR_FALSE), mContextNode(aNode), mCount(0), mType(aType),
|
||||
mContextSize(0), mContextPosition(0), mDynFunc(PR_FALSE), mNext(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsMDGNode);
|
||||
}
|
||||
|
||||
nsXFormsMDGNode::~nsXFormsMDGNode()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXFormsMDGNode);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGNode::SetExpression(nsIDOMXPathExpression* aExpression, PRBool aDynFunc,
|
||||
PRInt32 aContextPosition, PRInt32 aContextSize)
|
||||
{
|
||||
mHasExpr = PR_TRUE;
|
||||
mDynFunc = aDynFunc;
|
||||
mExpression = aExpression;
|
||||
mContextPosition = aContextPosition;
|
||||
mContextSize = aContextSize;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGNode::HasExpr() const
|
||||
{
|
||||
return mHasExpr;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGNode::IsDirty() const
|
||||
{
|
||||
// A node is always dirty, if it depends on a dynamic function.
|
||||
return mDirty || mDynFunc;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGNode::MarkDirty()
|
||||
{
|
||||
mDirty = PR_TRUE;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGNode::MarkClean()
|
||||
{
|
||||
mDirty = PR_FALSE;
|
||||
}
|
||||
|
||||
/* ------------------------------------ */
|
||||
/* -------- nsXFormsMDGEngine --------- */
|
||||
/* ------------------------------------ */
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsMDGEngine)
|
||||
|
||||
nsXFormsMDGEngine::nsXFormsMDGEngine(nsXFormsMDG* aOwner)
|
||||
: mNodesInGraph(0), mOwner(aOwner)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsMDGEngine);
|
||||
}
|
||||
|
||||
nsXFormsMDGEngine::~nsXFormsMDGEngine()
|
||||
{
|
||||
mNodeToMDG.Enumerate(DeleteLinkedNodes, nsnull);
|
||||
|
||||
MOZ_COUNT_DTOR(nsXFormsMDGEngine);
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsXFormsMDGEngine::DeleteLinkedNodes(nsISupports *aKey, nsAutoPtr<nsXFormsMDGNode>& aNode, void* aArg)
|
||||
{
|
||||
if (!aNode) {
|
||||
NS_WARNING("nsXFormsMDGEngine::DeleteLinkedNodes() called with aNode == nsnull!");
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
nsXFormsMDGNode* temp;
|
||||
nsXFormsMDGNode* next = aNode->mNext;
|
||||
|
||||
while (next) {
|
||||
temp = next;
|
||||
next = next->mNext;
|
||||
delete temp;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::Init()
|
||||
{
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (mNodeToFlag.Init() && mNodeToMDG.Init()) {
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsXFormsMDGNode*
|
||||
nsXFormsMDGEngine::GetNode(nsIDOMNode* aDomNode, ModelItemPropName aType, PRBool aCreate)
|
||||
{
|
||||
nsIDOMNode* nodeKey = aDomNode;
|
||||
nsXFormsMDGNode* nd = nsnull;
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("nsXFormsMDGEngine::GetNode(aDomNode=%p, aType=%d, aCreate=%d)\n", (void*) nodeKey, aType, aCreate);
|
||||
#endif
|
||||
|
||||
|
||||
// Find correct type
|
||||
if (mNodeToMDG.Get(nodeKey, &nd)) {
|
||||
while (nd && nd->mType != aType) {
|
||||
nd = nd->mNext;
|
||||
}
|
||||
}
|
||||
|
||||
// Eventually create node
|
||||
if (!nd && aCreate){
|
||||
nd = new nsXFormsMDGNode(nodeKey, aType);
|
||||
if (!nd) {
|
||||
NS_ERROR("Could not allocate room for new nsXFormsMDGNode");
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("\tNode not found, create new MDGNode '%p'\n", (void*) nd);
|
||||
#endif
|
||||
// Link to existing node
|
||||
nsXFormsMDGNode* nd_exists;
|
||||
if (mNodeToMDG.Get(nodeKey, &nd_exists)) {
|
||||
while (nd_exists->mNext) {
|
||||
nd_exists = nd_exists->mNext;
|
||||
}
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("\tLinking to existing MDGNode '%p'\n", (void*) nd_exists);
|
||||
#endif
|
||||
nd_exists->mNext = nd;
|
||||
} else {
|
||||
nodeKey->AddRef();
|
||||
if (!mNodeToMDG.Put(nodeKey, nd)) {
|
||||
delete nd;
|
||||
NS_ERROR("Could not insert new node in HashTable!");
|
||||
return nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
mNodesInGraph++;
|
||||
}
|
||||
return nd;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::Insert(nsIDOMNode* aContextNode, nsIDOMXPathExpression* aExpression,
|
||||
const nsXFormsMDGSet* aDependencies, PRBool aDynFunc,
|
||||
PRInt32 aContextPos, PRInt32 aContextSize,
|
||||
ModelItemPropName aType, ModelItemPropName aDepType)
|
||||
{
|
||||
NS_ENSURE_ARG(aContextNode);
|
||||
NS_ENSURE_ARG(aExpression);
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
nsAutoString nodename;
|
||||
aContextNode->GetNodeName(nodename);
|
||||
printf("nsXFormsMDGEngine::Insert(aContextNode=%s, aExpression=n/a, aDependencies=|%d|,\n",
|
||||
NS_ConvertUCS2toUTF8(nodename).get(),
|
||||
aDependencies->Count());
|
||||
printf(" aContextPos=%d, aContextSize=%d, aType=%d, aDepType=%d,\n",
|
||||
aContextPos, aContextSize, aType, aDepType);
|
||||
printf(" aDynFunc=%d)\n",
|
||||
aDynFunc);
|
||||
#endif
|
||||
nsXFormsMDGNode* newnode = GetNode(aContextNode, aType);
|
||||
|
||||
if (!newnode) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (newnode->HasExpr()) {
|
||||
// MIP already in the graph. That is. there is already a MIP of the same
|
||||
// type for this node, which is illegal.
|
||||
// Example: <bind nodeset="x" required="true()" required="false()"/>
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
newnode->SetExpression(aExpression, aDynFunc, aContextPos, aContextSize);
|
||||
|
||||
// Add dependencies
|
||||
if (aDependencies) {
|
||||
nsCOMPtr<nsIDOMNode> dep_domnode;
|
||||
nsXFormsMDGNode* dep_gnode;
|
||||
for (PRInt32 i = 0; i < aDependencies->Count(); ++i) {
|
||||
dep_domnode = aDependencies->GetNode(i);
|
||||
if (!dep_domnode) {
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
}
|
||||
|
||||
dep_gnode = GetNode(dep_domnode, aDepType);
|
||||
if (!dep_gnode) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (aType == aDepType && dep_gnode->mContextNode == aContextNode) {
|
||||
// Reference to itself, ignore
|
||||
continue;
|
||||
}
|
||||
|
||||
dep_gnode->mSuc.AppendElement(newnode);
|
||||
newnode->mCount++;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsXFormsMDGEngine::AddStartNodes(nsISupports *aKey, nsXFormsMDGNode* aNode, void* aDeque)
|
||||
{
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("nsXFormsMDGEngine::AddStartNodes(aKey=n/a, aNode=%p, aDeque=%p)\n", (void*) aNode, aDeque);
|
||||
#endif
|
||||
|
||||
nsDeque* deque = NS_STATIC_CAST(nsDeque*, aDeque);
|
||||
if (!deque) {
|
||||
NS_ERROR("nsXFormsMDGEngine::AddStartNodes called with NULL aDeque");
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
|
||||
while (aNode) {
|
||||
if (aNode->mCount == 0) {
|
||||
// Is it not possible to check error condition?
|
||||
deque->Push(aNode);
|
||||
}
|
||||
aNode = aNode->mNext;
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::Rebuild()
|
||||
{
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("nsXFormsMDGEngine::Rebuild()\n");
|
||||
#endif
|
||||
nsresult rv = NS_OK;
|
||||
mJustRebuilt = PR_TRUE;
|
||||
mFirstCalculate = PR_FALSE;
|
||||
|
||||
mGraph.Clear();
|
||||
mNodeToFlag.Clear();
|
||||
|
||||
nsDeque sortedNodes(nsnull);
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("\tmNodesInGraph: %d\n", mNodesInGraph);
|
||||
printf("\tmNodeToMDG: %d\n", mNodeToMDG.Count());
|
||||
printf("\tmNodeToFlag: %d\n", mNodeToFlag.Count());
|
||||
#endif
|
||||
|
||||
// Initial scan for nsXFormsMDGNodes with no dependencies (count == 0)
|
||||
PRUint32 entries = mNodeToMDG.EnumerateRead(AddStartNodes, &sortedNodes);
|
||||
if (entries != mNodeToMDG.Count()) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("\tStartNodes: %d\n", sortedNodes.GetSize());
|
||||
#endif
|
||||
|
||||
|
||||
nsXFormsMDGNode* node;
|
||||
while ((node = NS_STATIC_CAST(nsXFormsMDGNode*, sortedNodes.Pop()))) {
|
||||
for (PRInt32 i = 0; i < node->mSuc.Count(); ++i) {
|
||||
nsXFormsMDGNode* sucNode = NS_STATIC_CAST(nsXFormsMDGNode*, node->mSuc[i]);
|
||||
NS_ASSERTION(sucNode, "XForms: NULL successor node");
|
||||
|
||||
sucNode->mCount--;
|
||||
if (sucNode->mCount == 0) {
|
||||
sortedNodes.Push(sucNode);
|
||||
}
|
||||
}
|
||||
|
||||
node->MarkDirty();
|
||||
|
||||
if (!mGraph.AppendElement(node)) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (mGraph.Count() != mNodesInGraph) {
|
||||
NS_WARNING("XForms: There are loops in the MDG\n");
|
||||
rv = NS_ERROR_ABORT;
|
||||
}
|
||||
|
||||
mNodesInGraph = 0;
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGEngine::Clear() {
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("nsXFormsMDGEngine::Clear()\n");
|
||||
#endif
|
||||
|
||||
mNodeToMDG.Enumerate(DeleteLinkedNodes, nsnull);
|
||||
mNodeToMDG.Clear();
|
||||
|
||||
mNodeToFlag.Clear();
|
||||
|
||||
mGraph.Clear();
|
||||
|
||||
mNodesInGraph = 0;
|
||||
}
|
||||
|
||||
PLDHashOperator
|
||||
nsXFormsMDGEngine::AndFlag(nsISupports *aKey, PRUint16& aFlag, void* aMask)
|
||||
{
|
||||
PRUint16* andMask = NS_STATIC_CAST(PRUint16*, aMask);
|
||||
if (!andMask) {
|
||||
return PL_DHASH_STOP;
|
||||
}
|
||||
aFlag &= *andMask;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGEngine::AndFlags(PRUint16 aAndMask)
|
||||
{
|
||||
PRUint32 entries = mNodeToFlag.Enumerate(AndFlag, &aAndMask);
|
||||
return (entries == mNodeToFlag.Count()) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
PRUint16
|
||||
nsXFormsMDGEngine::GetFlag(nsIDOMNode* aDomNode)
|
||||
{
|
||||
PRUint16 flag = MDG_FLAG_DEFAULT | (mJustRebuilt && mFirstCalculate ? MDG_FLAG_INITIAL_DISPATCH : 0);
|
||||
|
||||
// If node is found, flag is modified, if not flag is untouched
|
||||
mNodeToFlag.Get(aDomNode, &flag);
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGEngine::SetFlag(nsIDOMNode* aDomNode, PRUint16 aFlag)
|
||||
{
|
||||
nsIDOMNode *nodeKey = aDomNode;
|
||||
nodeKey->AddRef();
|
||||
mNodeToFlag.Put(nodeKey, aFlag);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGEngine::OrFlag(nsIDOMNode* aDomNode, PRInt16 aFlag)
|
||||
{
|
||||
PRUint16 fl = GetFlag(aDomNode);
|
||||
fl |= aFlag;
|
||||
SetFlag(aDomNode, fl);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGEngine::SetFlagBits(nsIDOMNode* aDomNode, PRUint16 aBits, PRBool aOn)
|
||||
{
|
||||
PRUint32 fl = GetFlag(aDomNode);
|
||||
if (aOn) {
|
||||
fl |= aBits;
|
||||
} else {
|
||||
fl &= ~aBits;
|
||||
}
|
||||
SetFlag(aDomNode, fl);
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::BooleanExpression(nsXFormsMDGNode* aNode, PRBool& state)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNode);
|
||||
|
||||
// TODO: Use aNode->contextPosition and aNode->contextSize!
|
||||
nsISupports* retval;
|
||||
nsresult rv;
|
||||
|
||||
rv = aNode->mExpression->Evaluate(aNode->mContextNode, nsIDOMXPathResult::BOOLEAN_TYPE, nsnull, &retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMXPathResult> xpath_res = do_QueryInterface(retval);
|
||||
NS_ENSURE_TRUE(xpath_res, NS_ERROR_FAILURE);
|
||||
|
||||
rv = xpath_res->GetBooleanValue(&state);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::ComputeMIP(PRUint16 aStateFlag, PRUint16 aDispatchFlag, nsXFormsMDGNode* aNode, PRBool& aDidChange)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aNode);
|
||||
|
||||
PRUint32 word = GetFlag(aNode->mContextNode);
|
||||
PRBool state;
|
||||
nsresult rv = BooleanExpression(aNode, state);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRBool cstate = ((word & aStateFlag) != 0) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
if (state) {
|
||||
word |= aStateFlag;
|
||||
} else {
|
||||
word &= ~aStateFlag;
|
||||
}
|
||||
|
||||
aDidChange = (state != cstate) ? PR_TRUE : PR_FALSE;
|
||||
if (aDidChange) {
|
||||
word |= aDispatchFlag;
|
||||
}
|
||||
|
||||
SetFlag(aNode->mContextNode, word);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::ComputeMIPWithInheritance(PRUint16 aStateFlag, PRUint16 aDispatchFlag, PRUint16 aInheritanceFlag, nsXFormsMDGNode* aNode, nsXFormsMDGSet& aSet)
|
||||
{
|
||||
nsresult rv;
|
||||
PRBool didChange;
|
||||
rv = ComputeMIP(aStateFlag, aDispatchFlag, aNode, didChange);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (didChange) {
|
||||
PRUint16 flag = GetFlag(aNode->mContextNode);
|
||||
PRBool state = (flag & aStateFlag != 0) ? PR_TRUE : PR_FALSE;
|
||||
if ( (aStateFlag == MDG_FLAG_READONLY && (flag & aInheritanceFlag) == 0)
|
||||
|| (aStateFlag == MDG_FLAG_RELEVANT && (flag & aInheritanceFlag) > 0) )
|
||||
{
|
||||
NS_ENSURE_TRUE(aSet.AddNode(aNode->mContextNode), NS_ERROR_FAILURE);
|
||||
rv = AttachInheritance(aSet, aNode->mContextNode, state, aStateFlag);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::AttachInheritance(nsXFormsMDGSet& aSet, nsIDOMNode* aSrc, PRBool aState, PRUint16 aStateFlag)
|
||||
{
|
||||
NS_ENSURE_ARG(aSrc);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRUint32 flag;
|
||||
PRBool cstate;
|
||||
nsresult rv;
|
||||
PRBool updateNode = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> childList;
|
||||
rv = aSrc->GetChildNodes(getter_AddRefs(childList));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint32 childCount;
|
||||
rv = childList->GetLength(&childCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
for (PRUint32 i = 0; i < childCount; i++) {
|
||||
rv = childList->Item(i, getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(node, NS_ERROR_FAILURE);
|
||||
|
||||
flag = GetFlag(node);
|
||||
|
||||
cstate = ((flag & aStateFlag) != 0) ? PR_TRUE : PR_FALSE;
|
||||
|
||||
if (aStateFlag == MDG_FLAG_RELEVANT) {
|
||||
if (aState == PR_FALSE) { // The nodes are getting irrelevant
|
||||
if ((flag & MDG_FLAG_INHERITED_RELEVANT) != 0 && cstate) {
|
||||
flag &= ~MDG_FLAG_INHERITED_RELEVANT;
|
||||
flag |= MDG_FLAG_DISPATCH_RELEVANT_CHANGED;
|
||||
updateNode = PR_TRUE;
|
||||
}
|
||||
} else { // The nodes are becoming relevant
|
||||
if (cstate) {
|
||||
flag |= MDG_FLAG_DISPATCH_RELEVANT_CHANGED; // Relevant has changed from inheritance
|
||||
flag |= MDG_FLAG_INHERITED_RELEVANT; // Clear the flag for inheritance
|
||||
updateNode = PR_TRUE;
|
||||
}
|
||||
}
|
||||
} else if (aStateFlag == MDG_FLAG_READONLY) {
|
||||
if (aState) { // The nodes are getting readonly
|
||||
if ((flag & MDG_FLAG_INHERITED_READONLY) == 0 && cstate == PR_FALSE) {
|
||||
flag |= MDG_FLAG_INHERITED_READONLY | MDG_FLAG_DISPATCH_READONLY_CHANGED;
|
||||
updateNode = PR_TRUE;
|
||||
}
|
||||
} else { // The nodes are getting readwrite
|
||||
if (cstate) {
|
||||
flag |= MDG_FLAG_DISPATCH_READONLY_CHANGED;
|
||||
flag &= ~MDG_FLAG_INHERITED_READONLY;
|
||||
updateNode = PR_TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (updateNode) {
|
||||
SetFlag(node, flag);
|
||||
rv = AttachInheritance(aSet, node, aState, aStateFlag);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_TRUE(aSet.AddNode(node), NS_ERROR_FAILURE);
|
||||
updateNode = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::Calculate(nsXFormsMDGSet& aValueChanged)
|
||||
{
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("nsXFormsMDGEngine::Calculcate(aValueChanged=|%d|)\n", aValueChanged.Count());
|
||||
#endif
|
||||
|
||||
NS_ENSURE_TRUE(aValueChanged.AddSet(mMarkedNodes), NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
mMarkedNodes.Clear();
|
||||
|
||||
PRBool res = PR_TRUE;
|
||||
|
||||
mFirstCalculate = mJustRebuilt;
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("\taValueChanged: %d\n", aValueChanged.Count());
|
||||
printf("\tmNodeToMDG: %d\n", mNodeToFlag.Count());
|
||||
printf("\tmNodeToFlag: %d\n", mNodeToFlag.Count());
|
||||
printf("\tGraph nodes: %d\n", mGraph.Count());
|
||||
#endif
|
||||
|
||||
// Go through all dirty nodes in the graph
|
||||
nsresult rv;
|
||||
nsXFormsMDGNode* g;
|
||||
for (PRInt32 i = 0; i < mGraph.Count(); ++i) {
|
||||
g = NS_STATIC_CAST(nsXFormsMDGNode*, mGraph[i]);
|
||||
|
||||
if (!g) {
|
||||
NS_WARNING("nsXFormsMDGEngine::Calculcate(): Empty node in graph!!!");
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
nsAutoString domNodeName;
|
||||
g->mContextNode->GetNodeName(domNodeName);
|
||||
|
||||
printf("\tNode #%d: This=%p, Dirty=%d, DynFunc=%d, Type=%d, Count=%d, Suc=%d, CSize=%d, CPos=%d, Next=%p, domnode=%s\n",
|
||||
i, (void*) g, g->IsDirty(), g->mDynFunc, g->mType, g->mCount, g->mSuc.Count(),
|
||||
g->mContextSize, g->mContextPosition, (void*) g->mNext, NS_ConvertUCS2toUTF8(domNodeName).get());
|
||||
#endif
|
||||
|
||||
// Ignore node if it is not dirty
|
||||
if (!g->IsDirty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PRBool constraint = PR_TRUE;
|
||||
// Find MIP-type and handle it accordingly
|
||||
switch (g->mType) {
|
||||
case eModel_calculate:
|
||||
if (g->HasExpr()) {
|
||||
nsISupports* retval;
|
||||
rv = g->mExpression->Evaluate(g->mContextNode, nsIDOMXPathResult::STRING_TYPE, nsnull, &retval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIDOMXPathResult> xpath_res = do_QueryInterface(retval);
|
||||
NS_ENSURE_TRUE(xpath_res, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
nsAutoString nodeval;
|
||||
rv = xpath_res->GetStringValue(nodeval);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = mOwner->SetNodeValue(g->mContextNode, nodeval);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
NS_ENSURE_TRUE(aValueChanged.AddNode(g->mContextNode), NS_ERROR_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
OrFlag(g->mContextNode, MDG_FLAG_DISPATCH_VALUE_CHANGED);// | MDG_FLAG_DISPATCH_READONLY_CHANGED | MDG_FLAG_DISPATCH_VALID_CHANGED | MDG_FLAG_DISPATCH_RELEVANT_CHANGED);
|
||||
break;
|
||||
|
||||
case eModel_constraint:
|
||||
if (g->HasExpr()) {
|
||||
rv = BooleanExpression(g, constraint);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
// TODO: Schema validity should be checked here
|
||||
|
||||
if ((GetFlag(g->mContextNode) & MDG_FLAG_CONSTRAINT) > 0 != constraint) {
|
||||
SetFlagBits(g->mContextNode, MDG_FLAG_CONSTRAINT, constraint);
|
||||
SetFlagBits(g->mContextNode, MDG_FLAG_DISPATCH_VALID_CHANGED, PR_TRUE);
|
||||
NS_ENSURE_TRUE(aValueChanged.AddNode(g->mContextNode), NS_ERROR_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
case eModel_readonly:
|
||||
if (g->HasExpr()) {
|
||||
rv = ComputeMIPWithInheritance(MDG_FLAG_READONLY, MDG_FLAG_DISPATCH_READONLY_CHANGED, MDG_FLAG_INHERITED_READONLY, g, aValueChanged);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
break;
|
||||
|
||||
case eModel_relevant:
|
||||
if (g->HasExpr()) {
|
||||
rv = ComputeMIPWithInheritance(MDG_FLAG_RELEVANT, MDG_FLAG_DISPATCH_RELEVANT_CHANGED, MDG_FLAG_INHERITED_RELEVANT, g, aValueChanged);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
break;
|
||||
|
||||
case eModel_required:
|
||||
PRBool didChange;
|
||||
rv = ComputeMIP(MDG_FLAG_REQUIRED, MDG_FLAG_DISPATCH_REQUIRED_CHANGED, g, didChange);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (g->HasExpr() && didChange) {
|
||||
NS_ENSURE_TRUE(aValueChanged.AddNode(g->mContextNode), NS_ERROR_FAILURE);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
NS_ERROR("There was no expression which matched\n");
|
||||
res = PR_FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
// Mark successors dirty
|
||||
nsXFormsMDGNode* sucnode;
|
||||
for (PRInt32 j = 0; j < g->mSuc.Count(); ++j) {
|
||||
sucnode = NS_STATIC_CAST(nsXFormsMDGNode*, g->mSuc[j]);
|
||||
if (!sucnode) {
|
||||
NS_ERROR("nsXFormsMDGEngine::Calculate(): Node has NULL successor!");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
sucnode->MarkDirty();
|
||||
}
|
||||
|
||||
g->MarkClean();
|
||||
}
|
||||
aValueChanged.MakeUnique();
|
||||
|
||||
#ifdef DEBUG_XF_MDG
|
||||
printf("\taValueChanged: %d\n", aValueChanged.Count());
|
||||
printf("\tmNodeToMDG: %d\n", mNodeToFlag.Count());
|
||||
printf("\tmNodeToFlag: %d\n", mNodeToFlag.Count());
|
||||
printf("\tGraph nodes: %d\n", mGraph.Count());
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// TODO: This function needs to be called
|
||||
nsresult
|
||||
nsXFormsMDGEngine::MarkNode(nsIDOMNode* aDomNode)
|
||||
{
|
||||
SetFlagBits(aDomNode, MDG_FLAG_ALL_DISPATCH, PR_TRUE);
|
||||
|
||||
nsXFormsMDGNode* n = GetNode(aDomNode, eModel_calculate);
|
||||
if (n) {
|
||||
n->MarkDirty();
|
||||
}
|
||||
|
||||
// Add constraint to trigger validation of node
|
||||
n = GetNode(aDomNode, eModel_constraint, PR_FALSE);
|
||||
if (!n) {
|
||||
n = GetNode(aDomNode, eModel_constraint, PR_TRUE);
|
||||
if (!n) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
NS_ENSURE_TRUE(mGraph.AppendElement(n), NS_ERROR_OUT_OF_MEMORY);
|
||||
}
|
||||
|
||||
n->MarkDirty();
|
||||
|
||||
NS_ENSURE_TRUE(mMarkedNodes.AddNode(aDomNode), NS_ERROR_FAILURE);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGEngine::ClearDispatchFlags()
|
||||
{
|
||||
mJustRebuilt = PR_FALSE;
|
||||
return AndFlags(MDG_FLAGMASK_NOT_DISPATCH);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsMDGEngine::Invalidate()
|
||||
{
|
||||
nsXFormsMDGNode* g;
|
||||
for (PRInt32 i = 0; i < mGraph.Count(); ++i) {
|
||||
g = NS_STATIC_CAST(nsXFormsMDGNode*, mGraph[i]);
|
||||
NS_ENSURE_TRUE(g, NS_ERROR_FAILURE);
|
||||
g->MarkDirty();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGEngine::TestAndClear(nsIDOMNode* aDomNode, PRUint16 aFlag)
|
||||
{
|
||||
PRUint16 fl = GetFlag(aDomNode);
|
||||
PRUint16 test = fl & aFlag;
|
||||
fl &= ~aFlag;
|
||||
SetFlag(aDomNode, fl);
|
||||
return (test != 0) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGEngine::TestAndSet(nsIDOMNode* aDomNode, PRUint16 aFlag)
|
||||
{
|
||||
PRUint16 fl = GetFlag(aDomNode);
|
||||
PRUint16 test = fl & aFlag;
|
||||
fl |= aFlag;
|
||||
SetFlag(aDomNode, fl);
|
||||
return (test != 0) ? PR_TRUE : PR_FALSE;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGEngine::Test(nsIDOMNode* aDomNode, PRUint16 aFlag)
|
||||
{
|
||||
PRUint16 fl = GetFlag(aDomNode);
|
||||
PRUint16 test = fl & aFlag;
|
||||
return (test != 0) ? PR_TRUE : PR_FALSE;
|
||||
}
|
|
@ -0,0 +1,430 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSXFORMSMDGENGINE__
|
||||
#define __NSXFORMSMDGENGINE__
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsClassHashtable.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsXFormsTypes.h"
|
||||
#include "nsXFormsMDGSet.h"
|
||||
|
||||
class nsIDOMXPathExpression;
|
||||
class nsXFormsMDG;
|
||||
|
||||
/**
|
||||
* Flags, etc.
|
||||
*
|
||||
* TODO: Convert to enum?
|
||||
*/
|
||||
const PRUint16 MDG_FLAG_READONLY = 1 << 1;
|
||||
const PRUint16 MDG_FLAG_CONSTRAINT = 1 << 2;
|
||||
const PRUint16 MDG_FLAG_RELEVANT = 1 << 3;
|
||||
const PRUint16 MDG_FLAG_REQUIRED = 1 << 4;
|
||||
const PRUint16 MDG_FLAG_SCHEMA_VALID = 1 << 5;
|
||||
const PRUint16 MDG_FLAG_VALID = 1 << 6;
|
||||
const PRUint16 MDG_FLAG_INHERITED_RELEVANT = 1 << 7;
|
||||
const PRUint16 MDG_FLAG_INHERITED_READONLY = 1 << 8;
|
||||
const PRUint16 MDG_FLAG_DISPATCH_VALUE_CHANGED = 1 << 9;
|
||||
const PRUint16 MDG_FLAG_DISPATCH_READONLY_CHANGED = 1 << 10;
|
||||
const PRUint16 MDG_FLAG_DISPATCH_VALID_CHANGED = 1 << 11;
|
||||
const PRUint16 MDG_FLAG_DISPATCH_RELEVANT_CHANGED = 1 << 12;
|
||||
const PRUint16 MDG_FLAG_DISPATCH_REQUIRED_CHANGED = 1 << 13;
|
||||
const PRUint16 MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED = 1 << 14;
|
||||
|
||||
const PRUint16 MDG_FLAGMASK_NOT_DISPATCH = ~(MDG_FLAG_DISPATCH_VALUE_CHANGED | \
|
||||
MDG_FLAG_DISPATCH_READONLY_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_VALID_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_REQUIRED_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED);
|
||||
|
||||
const PRUint16 MDG_FLAG_DEFAULT = MDG_FLAG_CONSTRAINT | \
|
||||
MDG_FLAG_RELEVANT |\
|
||||
MDG_FLAG_INHERITED_RELEVANT;
|
||||
|
||||
const PRUint16 MDG_FLAG_INITIAL_DISPATCH = MDG_FLAG_DISPATCH_READONLY_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_VALID_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_REQUIRED_CHANGED;
|
||||
|
||||
const PRUint16 MDG_FLAG_ALL_DISPATCH = MDG_FLAG_DISPATCH_READONLY_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_VALID_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_RELEVANT_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_REQUIRED_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_VALUE_CHANGED |\
|
||||
MDG_FLAG_DISPATCH_CONSTRAINT_CHANGED;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Data structure for nodes in the graph.
|
||||
*
|
||||
* There is one node per type (calculate, readonly, etc) for each nsIDOMNode.
|
||||
* All nsXFormsMDGNodes for same nsIDOMNode are linked together via 'next'.
|
||||
*/
|
||||
class nsXFormsMDGNode {
|
||||
private:
|
||||
/** Dirty flag */
|
||||
PRBool mDirty;
|
||||
|
||||
/** Does this node have an XPath expression attached to it */
|
||||
PRBool mHasExpr;
|
||||
|
||||
public:
|
||||
/** Pointer to the nsIDOMNode */
|
||||
nsCOMPtr<nsIDOMNode> mContextNode;
|
||||
|
||||
/** The XPath expression for this node */
|
||||
nsCOMPtr<nsIDOMXPathExpression> mExpression;
|
||||
|
||||
/** List of nodes that depend on this node */
|
||||
nsVoidArray mSuc;
|
||||
|
||||
/** Number of nodes that this node depends on */
|
||||
unsigned int mCount;
|
||||
|
||||
/** The type */
|
||||
ModelItemPropName mType;
|
||||
|
||||
/** (XPath) Context size for this node */
|
||||
int mContextSize;
|
||||
|
||||
/** (XPath) Position for this node */
|
||||
int mContextPosition;
|
||||
|
||||
/** Does expression use dynamic functions */
|
||||
PRBool mDynFunc;
|
||||
|
||||
/** Pointer to next nsXFormsMDGNode with same nsIDOMNode, but different type */
|
||||
nsXFormsMDGNode* mNext;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param aNode The context node
|
||||
* @param aType The type of node (calculate, readonly, etc.)
|
||||
*/
|
||||
nsXFormsMDGNode(nsIDOMNode* aNode, const ModelItemPropName aType);
|
||||
|
||||
/** Destructor */
|
||||
~nsXFormsMDGNode();
|
||||
|
||||
/**
|
||||
* Sets the XPath expression for the node.
|
||||
*
|
||||
* @param aExpression The XPath expression
|
||||
* @param aDynFunc Whether expression uses dynamic functions
|
||||
* @param aContextPosition The context position for the expression
|
||||
* @param aContextSize The context size for the expression
|
||||
*/
|
||||
void SetExpression(nsIDOMXPathExpression* aExpression, PRBool aDynFunc,
|
||||
PRInt32 aContextPosition, PRInt32 aContextSize);
|
||||
|
||||
/** Does node have an expression? */
|
||||
PRBool HasExpr() const;
|
||||
|
||||
/** Is node dirty? */
|
||||
PRBool IsDirty() const;
|
||||
|
||||
/* Mark node clean */
|
||||
void MarkClean();
|
||||
|
||||
/* Mark node dirty */
|
||||
void MarkDirty();
|
||||
};
|
||||
|
||||
/**
|
||||
* The Multi Dependency Graph (MDG) Engine.
|
||||
*
|
||||
* This class handles all the necessary logic to create and maintain the MDG,
|
||||
* and update the instance data accordingly.
|
||||
*
|
||||
* A bit about the graph:
|
||||
* As specified in the spec., one node (nsXFormsMDGNode) is created in the graph for
|
||||
* each of the attributes (readonly, calculate, etc.) for a nsIDOMNode. These graph
|
||||
* nodes are owned by the mNodeToMDG hash table, which maps from a nsIDOMNode to
|
||||
* the first node in a single-linked list (mNext) of nodes for the same nsIDOMNode.
|
||||
*/
|
||||
class nsXFormsMDGEngine {
|
||||
protected:
|
||||
/**
|
||||
* Maps from nsIDOMNode to nsXFormsMDGNode(s)
|
||||
*/
|
||||
nsClassHashtable<nsISupportsHashKey, nsXFormsMDGNode> mNodeToMDG;
|
||||
|
||||
/**
|
||||
* Maps from nsIDOMNode to flag (MDG_FLAG_*)
|
||||
*/
|
||||
nsDataHashtable<nsISupportsHashKey, PRUint16> mNodeToFlag;
|
||||
|
||||
/**
|
||||
* True when Rebuild() has been run, but not ClearDispatchFlags()
|
||||
*/
|
||||
PRBool mJustRebuilt;
|
||||
|
||||
/**
|
||||
* True when last Calculate() was run when mJustRebuilded was true.
|
||||
*/
|
||||
PRBool mFirstCalculate;
|
||||
|
||||
/** The actual MDG */
|
||||
nsVoidArray mGraph;
|
||||
|
||||
/** Set of nodes that are marked as changed, and should be included in recalculation */
|
||||
nsXFormsMDGSet mMarkedNodes;
|
||||
|
||||
/** Number of nodes in the graph */
|
||||
PRInt32 mNodesInGraph;
|
||||
|
||||
/** Hidden copy constructor */
|
||||
nsXFormsMDGEngine(nsXFormsMDGEngine&) {}
|
||||
|
||||
/**
|
||||
* Used by Clear() and ~ to delete the linked nodes in mNodeToMDG, the hash table
|
||||
* itself handles the main nodes.
|
||||
*/
|
||||
static PLDHashOperator PR_CALLBACK DeleteLinkedNodes(nsISupports *aKey, nsAutoPtr<nsXFormsMDGNode>& aNode, void* aArg);
|
||||
|
||||
/**
|
||||
* Used by Rebuild() to find the start nodes for mGraph, that is nodes
|
||||
* where mCount == 0.
|
||||
*/
|
||||
static PLDHashOperator PR_CALLBACK AddStartNodes(nsISupports *aKey, nsXFormsMDGNode* aNode, void* aDeque);
|
||||
|
||||
/**
|
||||
* Used by AndFlags() to boolean AND all flags with aMask.
|
||||
*/
|
||||
static PLDHashOperator PR_CALLBACK AndFlag(nsISupports *aKey, PRUint16& aFlag, void* aMask);
|
||||
|
||||
/**
|
||||
* Retrieve a node from the graph.
|
||||
*
|
||||
* @param aDomNode The DOM node to retrieve
|
||||
* @param aType The type to retrieve (readonly, calculate, etc)
|
||||
* @param aCreate Create the node and insert it into the graph if it does not exist?
|
||||
* @return The node, nsnull if not found and aCreate != PR_TRUE
|
||||
*/
|
||||
nsXFormsMDGNode* GetNode(nsIDOMNode* aDomNode, ModelItemPropName aType, PRBool aCreate = PR_TRUE);
|
||||
|
||||
/**
|
||||
* Sets the flag for a node.
|
||||
*
|
||||
* @param aDomNode The node
|
||||
* @param aFlag The flag
|
||||
*/
|
||||
void SetFlag(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
||||
|
||||
/**
|
||||
* Boolean OR the existing flag on the node with a new flag
|
||||
*
|
||||
* @param aDomNode The node
|
||||
* @param aFlag The new flag
|
||||
*/
|
||||
void OrFlag(nsIDOMNode* aDomNode, PRInt16 aFlag);
|
||||
|
||||
/**
|
||||
* Retrieve the flag for a node.
|
||||
*
|
||||
* @param aDomNode The node
|
||||
* @return The flag
|
||||
*/
|
||||
PRUint16 GetFlag(nsIDOMNode* aDomNode);
|
||||
|
||||
/**
|
||||
* Sets a bit in the flag for a node
|
||||
*
|
||||
* @param aDomNode The node
|
||||
* @param aBit The bit position to set
|
||||
* @param aOn The bit value
|
||||
*/
|
||||
void SetFlagBits(nsIDOMNode* aDomNode, PRUint16 aBit, PRBool aOn);
|
||||
|
||||
/**
|
||||
* Boolean AND all flags with a mask.
|
||||
*
|
||||
* @param aAndMask The mask
|
||||
* @return Did operation succeed?
|
||||
*/
|
||||
PRBool AndFlags(PRUint16 aAndMask);
|
||||
|
||||
/**
|
||||
* Evaluates the expression for the given node and returns the boolean result.
|
||||
*
|
||||
* @param aNode The node to evaluate
|
||||
* @param res The result of the evaluation
|
||||
*/
|
||||
nsresult BooleanExpression(nsXFormsMDGNode* aNode, PRBool& res);
|
||||
|
||||
/**
|
||||
* Compute MIP value for node types with boolean result (all except calculate)
|
||||
*
|
||||
* @param aStateFlag The flag for the type of MIP
|
||||
* @param aDispatchFlag The dispatch flag
|
||||
* @param aNode The context node
|
||||
* @param aDidChange Was the node changed?
|
||||
*/
|
||||
nsresult ComputeMIP(PRUint16 aStateFlag, PRUint16 aDispatchFlag, nsXFormsMDGNode* aNode, PRBool& aDidChange);
|
||||
|
||||
/**
|
||||
* Same as ComputeMIP(), but also handles any inheritance of attributes.
|
||||
*
|
||||
* @param aStateFlag The flag for the type of MIP
|
||||
* @param aDispatchFlag The dispatch flag
|
||||
* @param aInheritanceFlag The inheritance flag for the type of MIP
|
||||
* @param aNode The context node
|
||||
* @param aSet Set of the nodes influenced by operation
|
||||
*/
|
||||
nsresult ComputeMIPWithInheritance(PRUint16 aStateFlag, PRUint16 aDispatchFlag, PRUint16 aInheritanceFlag, nsXFormsMDGNode* aNode, nsXFormsMDGSet& aSet);
|
||||
|
||||
/**
|
||||
* Attaches inheritance to all children of a given node
|
||||
*
|
||||
* @param aSet Set of the nodes influenced by operation
|
||||
* @param aSrc The node
|
||||
* @param aState The state of the flag
|
||||
* @param aStateFlag The flag
|
||||
*/
|
||||
nsresult AttachInheritance(nsXFormsMDGSet& aSet, nsIDOMNode* aSrc, PRBool aState, PRUint16 aStateFlag);
|
||||
|
||||
/** A pointer to the owner, used to access Get- and SetNodeValue() */
|
||||
nsXFormsMDG* mOwner;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param aOwner Pointer to the owner
|
||||
*/
|
||||
nsXFormsMDGEngine(nsXFormsMDG* aOwner);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~nsXFormsMDGEngine();
|
||||
|
||||
/**
|
||||
* Initializes the hash tables. Needs to be called before class is used!
|
||||
*/
|
||||
nsresult Init();
|
||||
|
||||
/**
|
||||
* Inserts a MIP into the graph
|
||||
*/
|
||||
nsresult Insert(nsIDOMNode* aContextNode, nsIDOMXPathExpression* aExpression,
|
||||
const nsXFormsMDGSet* aDependencies,
|
||||
PRBool aDynFunc,
|
||||
PRInt32 aContextPos, PRInt32 aContextSize,
|
||||
ModelItemPropName aType = eModel_calculate,
|
||||
ModelItemPropName aDeptype = eModel_calculate);
|
||||
|
||||
/**
|
||||
* Rebuilds the MDG.
|
||||
*
|
||||
* Does this by doing a topological sort of all nodes in mNodeToMDG, and storing
|
||||
* the result in mGraph.
|
||||
*
|
||||
* @note This has to be called before Calculate().
|
||||
*/
|
||||
nsresult Rebuild();
|
||||
|
||||
/**
|
||||
* Removes all node information from engine
|
||||
*/
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Perform a calculation on all dirty nodes
|
||||
*
|
||||
* @param aValueChanged The nodes which were changed by operation.
|
||||
*/
|
||||
nsresult Calculate(nsXFormsMDGSet& aValueChanged);
|
||||
|
||||
/**
|
||||
* Invalidate the information, ie. mark all nodes as dirty.
|
||||
*/
|
||||
nsresult Invalidate();
|
||||
|
||||
/**
|
||||
* Get flag value for node and clear flag.
|
||||
*
|
||||
* @param aDomNode The node
|
||||
* @param aFlag The flag
|
||||
* @return The flag value
|
||||
*/
|
||||
PRBool TestAndClear(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
||||
|
||||
/**
|
||||
* Get flag value for node and set flag.
|
||||
*
|
||||
* @param aDomNode The node
|
||||
* @param aFlag The flag
|
||||
* @return The flag value
|
||||
*/
|
||||
PRBool TestAndSet(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
||||
|
||||
/**
|
||||
* Get flag value for node
|
||||
*
|
||||
* @param aDomNode The node
|
||||
* @param aFlag The flag
|
||||
* @return The flag value
|
||||
*/
|
||||
PRBool Test(nsIDOMNode* aDomNode, PRUint16 aFlag);
|
||||
|
||||
/**
|
||||
* Clear dispatch flags for all nodes
|
||||
*
|
||||
* @return Did operation succeed?
|
||||
*/
|
||||
PRBool ClearDispatchFlags();
|
||||
|
||||
/**
|
||||
* Make a node as changed, ie. include in next Calculate
|
||||
*
|
||||
* @param aDomNode The node
|
||||
*/
|
||||
nsresult MarkNode(nsIDOMNode* aDomNode);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,97 @@
|
|||
#include "nsXFormsMDGSet.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsMDGSet)
|
||||
|
||||
nsXFormsMDGSet::nsXFormsMDGSet()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsMDGSet);
|
||||
}
|
||||
|
||||
nsXFormsMDGSet::~nsXFormsMDGSet() {
|
||||
Clear();
|
||||
|
||||
MOZ_COUNT_DTOR(nsXFormsMDGSet);
|
||||
}
|
||||
|
||||
int
|
||||
nsXFormsMDGSet::sortFunc(const void* aElement1, const void* aElement2, void* aData)
|
||||
{
|
||||
int res = 0;
|
||||
if (aElement1 < aElement2)
|
||||
res = -1;
|
||||
if (aElement1 > aElement2)
|
||||
res = 1;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsXFormsMDGSet::Clear()
|
||||
{
|
||||
// Remove reference counters
|
||||
nsISupports* node;
|
||||
for (PRInt32 i = 0; i < array.Count(); ++i) {
|
||||
node = NS_STATIC_CAST(nsISupports*, array[i]);
|
||||
node->Release();
|
||||
}
|
||||
// Clear array
|
||||
array.Clear();
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsMDGSet::MakeUnique()
|
||||
{
|
||||
array.Sort(sortFunc, nsnull);
|
||||
|
||||
// TODO: Assuming that moving element x, will delete x, and move list "one to the left",
|
||||
// ie. x = x+1, x+1=x+2, ... etc.
|
||||
// Is that correct?
|
||||
PRInt32 pos = 0;
|
||||
nsIDOMNode* node;
|
||||
while (pos + 1 < array.Count()) {
|
||||
if (array[pos] == array[pos + 1]) {
|
||||
node = NS_STATIC_CAST(nsIDOMNode*, array[pos + 1]);
|
||||
node->Release();
|
||||
array.RemoveElementAt(pos + 1);
|
||||
} else {
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsXFormsMDGSet::Count() const
|
||||
{
|
||||
return array.Count();
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGSet::AddNode(nsIDOMNode* aDomNode)
|
||||
{
|
||||
if (!aDomNode) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
aDomNode->AddRef();
|
||||
return array.AppendElement(aDomNode);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsMDGSet::AddSet(nsXFormsMDGSet& aSet)
|
||||
{
|
||||
nsIDOMNode* node;
|
||||
for (PRInt32 i = 0; i < aSet.array.Count(); ++i) {
|
||||
node = NS_STATIC_CAST(nsIDOMNode*, aSet.array[i]);
|
||||
if (!AddNode(node)) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsIDOMNode*
|
||||
nsXFormsMDGSet::GetNode(const PRInt32 aIndex) const {
|
||||
return NS_STATIC_CAST(nsIDOMNode*, array[aIndex]);
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSXFORMSMDGSET_H__
|
||||
#define __NSXFORMSMDGSET_H__
|
||||
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsIDOMNode.h"
|
||||
|
||||
/**
|
||||
* A simple "set" implementation. For now it is just a wrapper for nsVoidArray,
|
||||
* but nsVoidArray can be changed if a more suitable structure is found.
|
||||
*
|
||||
* It is not a set, in that no two same nodes can exist. You need to call
|
||||
* MakeUnique() manually for that to be true.
|
||||
*
|
||||
* The class owns the nsIDOMNodes that it stores, and manages the reference
|
||||
* counters automatically.
|
||||
*/
|
||||
class nsXFormsMDGSet {
|
||||
private:
|
||||
/** The data structure */
|
||||
nsVoidArray array;
|
||||
|
||||
/** The sorting function used by MakeUnique() */
|
||||
static int sortFunc(const void* aElement1, const void* aElement2, void* aData);
|
||||
|
||||
public:
|
||||
/** Constructor */
|
||||
nsXFormsMDGSet();
|
||||
|
||||
/** Destructor */
|
||||
~nsXFormsMDGSet();
|
||||
|
||||
/** Clears the struture (removes all stored data) */
|
||||
void Clear();
|
||||
|
||||
/**
|
||||
* Delete any duplicates (ie. make the set a set...).
|
||||
*
|
||||
* As a side effect, it also sorts the data structure by the data pointer in
|
||||
* ascending order.
|
||||
*/
|
||||
void MakeUnique();
|
||||
|
||||
/** Returns the number of members */
|
||||
PRInt32 Count() const;
|
||||
|
||||
/**
|
||||
* Adds a node to the set.
|
||||
*
|
||||
* @param aDomNode The node to add.
|
||||
* @return Did the storage succeed?
|
||||
*/
|
||||
PRBool AddNode(nsIDOMNode* aDomNode);
|
||||
|
||||
/**
|
||||
* Adds all nodes from another set to this set
|
||||
*
|
||||
* @param aSet The set to add nodes from
|
||||
* @return Did the operation succeed?
|
||||
*/
|
||||
PRBool AddSet(nsXFormsMDGSet& aSet);
|
||||
|
||||
/**
|
||||
* Get a specific node from the set
|
||||
*
|
||||
* @param aIndex The position of the node to get
|
||||
* @return The node
|
||||
*/
|
||||
nsIDOMNode* GetNode(const PRInt32 aIndex) const;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,944 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsModelElement.h"
|
||||
#include "nsIXTFGenericElementWrapper.h"
|
||||
#include "nsMemory.h"
|
||||
#include "nsIDOMDocumentEvent.h"
|
||||
#include "nsIDOMEvent.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsIDOMNodeList.h"
|
||||
#include "nsString.h"
|
||||
#include "nsIDocument.h"
|
||||
#include "nsXFormsAtoms.h"
|
||||
#include "nsINameSpaceManager.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsINodeInfo.h"
|
||||
#include "nsIDOMDOMImplementation.h"
|
||||
#include "nsIDOMXMLDocument.h"
|
||||
#include "nsIDOMEventReceiver.h"
|
||||
#include "nsIDOMXPathResult.h"
|
||||
#include "nsIDOMXPathEvaluator.h"
|
||||
#include "nsIDOMXPathNSResolver.h"
|
||||
#include "nsIDOMXPathExpression.h"
|
||||
#include "nsIDOM3EventTarget.h"
|
||||
#include "nsIDOMEventGroup.h"
|
||||
#include "nsIDOMNSUIEvent.h"
|
||||
#include "nsIScriptGlobalObject.h"
|
||||
#include "nsIContent.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsXFormsControl.h"
|
||||
#include "nsXFormsTypes.h"
|
||||
#include "nsXFormsXPathParser.h"
|
||||
#include "nsXFormsXPathAnalyzer.h"
|
||||
#include "nsXFormsInstanceElement.h"
|
||||
|
||||
#include "nsISchemaLoader.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
#ifdef DEBUG_beaufour
|
||||
#include "nsIDOMSerializer.h"
|
||||
#endif
|
||||
|
||||
static const nsIID sScriptingIIDs[] = {
|
||||
NS_IDOMELEMENT_IID,
|
||||
NS_IDOMEVENTTARGET_IID,
|
||||
NS_IDOM3NODE_IID,
|
||||
NS_IXFORMSMODELELEMENT_IID
|
||||
};
|
||||
|
||||
struct EventData
|
||||
{
|
||||
const char *name;
|
||||
PRBool canCancel;
|
||||
PRBool canBubble;
|
||||
};
|
||||
|
||||
static const EventData sModelEvents[] = {
|
||||
{ "xforms-model-construct", PR_FALSE, PR_TRUE },
|
||||
{ "xforms-model-construct-done", PR_FALSE, PR_TRUE },
|
||||
{ "xforms-ready", PR_FALSE, PR_TRUE },
|
||||
{ "xforms-model-destruct", PR_FALSE, PR_TRUE },
|
||||
{ "xforms-rebuild", PR_TRUE, PR_TRUE },
|
||||
{ "xforms-refresh", PR_TRUE, PR_TRUE },
|
||||
{ "xforms-revalidate", PR_TRUE, PR_TRUE },
|
||||
{ "xforms-recalculate", PR_TRUE, PR_TRUE },
|
||||
{ "xforms-reset", PR_TRUE, PR_TRUE },
|
||||
{ "xforms-binding-exception", PR_FALSE, PR_TRUE },
|
||||
{ "xforms-link-exception", PR_FALSE, PR_TRUE },
|
||||
{ "xforms-link-error", PR_FALSE, PR_TRUE },
|
||||
{ "xforms-compute-exception", PR_FALSE, PR_TRUE }
|
||||
};
|
||||
|
||||
static nsIAtom* sModelPropsList[eModel__count];
|
||||
|
||||
struct nsXFormsModelElement::ModelItemProperties
|
||||
{
|
||||
nsCOMPtr<nsIDOMXPathExpression> properties[eModel__count];
|
||||
};
|
||||
|
||||
nsXFormsModelElement::nsXFormsModelElement()
|
||||
: mElement(nsnull),
|
||||
mSchemaCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ADDREF(nsXFormsModelElement)
|
||||
NS_IMPL_RELEASE(nsXFormsModelElement)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsXFormsModelElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFGenericElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXTFPrivate)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIXFormsModelElement)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISchemaLoadListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebServiceErrorHandler)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIXTFElement)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::OnDestroyed()
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mElement);
|
||||
NS_ASSERTION(receiver, "xml elements must be event receivers");
|
||||
|
||||
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||
NS_ASSERTION(systemGroup, "system event group must exist");
|
||||
|
||||
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mElement);
|
||||
for (unsigned int i = 0; i < NS_ARRAY_LENGTH(sModelEvents); ++i) {
|
||||
targ->RemoveGroupedEventListener(NS_ConvertUTF8toUTF16(sModelEvents[i].name),
|
||||
this, PR_FALSE, systemGroup);
|
||||
}
|
||||
|
||||
RemoveModelFromDocument();
|
||||
|
||||
mElement = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsModelElement::RemoveModelFromDocument()
|
||||
{
|
||||
// Find out if we are handling the model-construct-done for this document.
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
|
||||
nsIScriptGlobalObject *window = nsnull;
|
||||
if (doc)
|
||||
window = doc->GetScriptGlobalObject();
|
||||
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(window);
|
||||
if (targ) {
|
||||
nsVoidArray *models = NS_STATIC_CAST(nsVoidArray*,
|
||||
doc->GetProperty(nsXFormsAtoms::modelListProperty));
|
||||
|
||||
if (models) {
|
||||
if (models->SafeElementAt(0) == this) {
|
||||
nsXFormsModelElement *next =
|
||||
NS_STATIC_CAST(nsXFormsModelElement*, models->SafeElementAt(1));
|
||||
if (next) {
|
||||
targ->AddEventListener(NS_LITERAL_STRING("load"), next, PR_TRUE);
|
||||
}
|
||||
|
||||
targ->RemoveEventListener(NS_LITERAL_STRING("load"), this, PR_TRUE);
|
||||
}
|
||||
|
||||
models->RemoveElement(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetElementType(PRUint32 *aType)
|
||||
{
|
||||
*aType = ELEMENT_TYPE_GENERIC_ELEMENT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetIsAttributeHandler(PRBool *aIsHandler)
|
||||
{
|
||||
*aIsHandler = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
|
||||
{
|
||||
return CloneScriptingInterfaces(sScriptingIIDs,
|
||||
NS_ARRAY_LENGTH(sScriptingIIDs),
|
||||
aCount, aArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::WillChangeDocument(nsIDOMDocument* aNewDocument)
|
||||
{
|
||||
RemoveModelFromDocument();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteVoidArray(void *aObject,
|
||||
nsIAtom *aPropertyName,
|
||||
void *aPropertyValue,
|
||||
void *aData)
|
||||
{
|
||||
delete NS_STATIC_CAST(nsVoidArray*, aPropertyValue);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::DocumentChanged(nsIDOMDocument* aNewDocument)
|
||||
{
|
||||
// Add this model to the document's model list. If this is the first
|
||||
// model to be created, register an onload handler so that we can
|
||||
// do model-construct-done notifications.
|
||||
|
||||
if (!aNewDocument)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDocument> doc = do_QueryInterface(aNewDocument);
|
||||
|
||||
nsVoidArray *models = NS_STATIC_CAST(nsVoidArray*,
|
||||
doc->GetProperty(nsXFormsAtoms::modelListProperty));
|
||||
|
||||
if (!models) {
|
||||
models = new nsVoidArray(16);
|
||||
doc->SetProperty(nsXFormsAtoms::modelListProperty,
|
||||
models, DeleteVoidArray);
|
||||
|
||||
nsIScriptGlobalObject *window = doc->GetScriptGlobalObject();
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> targ = do_QueryInterface(window);
|
||||
targ->AddEventListener(NS_LITERAL_STRING("load"), this, PR_TRUE);
|
||||
}
|
||||
|
||||
models->AppendElement(this);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::WillChangeParent(nsIDOMElement* aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::ParentChanged(nsIDOMElement* aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::WillInsertChild(nsIDOMNode* aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::ChildInserted(nsIDOMNode* aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::WillAppendChild(nsIDOMNode* aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::ChildAppended(nsIDOMNode* aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::WillRemoveChild(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::ChildRemoved(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::WillSetAttribute(nsIAtom *aName,
|
||||
const nsAString &aNewValue)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::AttributeSet(nsIAtom *aName, const nsAString &aNewValue)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::WillRemoveAttribute(nsIAtom *aName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::DoneAddingChildren()
|
||||
{
|
||||
// We wait until all children are added to dispatch xforms-model-construct,
|
||||
// since the model may have an action handler for this event.
|
||||
|
||||
nsresult rv = DispatchEvent(eEvent_ModelConstruct);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// xforms-model-construct is not cancellable, so always proceed.
|
||||
// We continue here rather than doing this in HandleEvent since we know
|
||||
// it only makes sense to perform this default action once.
|
||||
|
||||
// (XForms 4.2.1)
|
||||
// 1. load xml schemas
|
||||
|
||||
nsAutoString schemaList;
|
||||
mElement->GetAttribute(NS_LITERAL_STRING("schema"), schemaList);
|
||||
if (!schemaList.IsEmpty()) {
|
||||
nsCOMPtr<nsISchemaLoader> loader = do_GetService(NS_SCHEMALOADER_CONTRACTID);
|
||||
NS_ENSURE_TRUE(loader, NS_ERROR_FAILURE);
|
||||
|
||||
// Parse the space-separated list.
|
||||
PRUint32 offset = 0;
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(mElement);
|
||||
nsRefPtr<nsIURI> baseURI = content->GetBaseURI();
|
||||
|
||||
while (1) {
|
||||
++mSchemaCount;
|
||||
PRInt32 index = schemaList.FindChar(PRUnichar(' '), offset);
|
||||
|
||||
nsCOMPtr<nsIURI> newURI;
|
||||
NS_NewURI(getter_AddRefs(newURI),
|
||||
Substring(schemaList, offset, index - offset),
|
||||
nsnull, baseURI);
|
||||
|
||||
if (!newURI) {
|
||||
DispatchEvent(eEvent_LinkException); // this is a fatal error
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCAutoString uriSpec;
|
||||
newURI->GetSpec(uriSpec);
|
||||
|
||||
rv = loader->LoadAsync(NS_ConvertUTF8toUTF16(uriSpec), this);
|
||||
if (NS_FAILED(rv)) {
|
||||
DispatchEvent(eEvent_LinkException); // this is a fatal error
|
||||
return NS_OK;
|
||||
}
|
||||
if (index == -1)
|
||||
break;
|
||||
|
||||
offset = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. construct an XPath data model from inline or external initial instance
|
||||
// data. This is done by our child instance elements as they are inserted
|
||||
// into the document, and all of the instances will be processed by this
|
||||
// point.
|
||||
|
||||
// XXX schema and external instance data loads should delay document onload
|
||||
|
||||
if (IsComplete()) {
|
||||
return FinishConstruction();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
|
||||
{
|
||||
aWrapper->SetNotificationMask(nsIXTFElement::NOTIFY_WILL_CHANGE_DOCUMENT |
|
||||
nsIXTFElement::NOTIFY_DOCUMENT_CHANGED |
|
||||
nsIXTFElement::NOTIFY_DONE_ADDING_CHILDREN);
|
||||
|
||||
nsCOMPtr<nsIDOMElement> node;
|
||||
aWrapper->GetElementNode(getter_AddRefs(node));
|
||||
|
||||
// It's ok to keep a weak pointer to mElement. mElement will have an
|
||||
// owning reference to this object, so as long as we null out mElement in
|
||||
// OnDestroyed, it will always be valid.
|
||||
|
||||
mElement = node;
|
||||
NS_ASSERTION(mElement, "Wrapper is not an nsIDOMElement, we'll crash soon");
|
||||
|
||||
nsresult rv = mMDG.Init();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIXTFPrivate
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetInner(nsISupports **aInner)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aInner);
|
||||
NS_ADDREF(*aInner = NS_STATIC_CAST(nsIXFormsModelElement*, this));
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIXFormsModelElement
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::GetInstanceDocument(const nsAString& aInstanceID,
|
||||
nsIDOMDocument **aDocument)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aDocument);
|
||||
|
||||
NS_IF_ADDREF(*aDocument = FindInstanceDocument(aInstanceID));
|
||||
return *aDocument ? NS_OK : NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Rebuild()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("nsXFormsModelElement::Rebuild()\n");
|
||||
#endif
|
||||
|
||||
// TODO: Clear graph and re-attach elements
|
||||
|
||||
// 1 . Clear graph
|
||||
// mMDG.Clear();
|
||||
|
||||
// 2. Re-attach all elements
|
||||
|
||||
// 3. Rebuild graph
|
||||
return mMDG.Rebuild();
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Recalculate()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("nsXFormsModelElement::Recalculate()\n");
|
||||
#endif
|
||||
|
||||
nsXFormsMDGSet changedNodes;
|
||||
// TODO: Handle changed nodes. That is, dispatch events, etc.
|
||||
|
||||
return mMDG.Recalculate(changedNodes);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Revalidate()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("nsXFormsModelElement::Revalidate()\n");
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG_beaufour
|
||||
// Dump instance document to stdout
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMSerializer> serializer(do_CreateInstance(NS_XMLSERIALIZER_CONTRACTID, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// TODO: Should use SerializeToStream and write directly to stdout...
|
||||
nsAutoString instanceString;
|
||||
rv = serializer->SerializeToString(mInstanceDocument, instanceString);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
printf("Instance data:\n%s\n", NS_ConvertUCS2toUTF8(instanceString).get());
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Refresh()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
printf("nsXFormsModelElement::Refresh()\n");
|
||||
#endif
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsISchemaLoadListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::OnLoad(nsISchema* aSchema)
|
||||
{
|
||||
mSchemas.AppendObject(aSchema);
|
||||
if (IsComplete()) {
|
||||
nsresult rv = FinishConstruction();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
DispatchEvent(eEvent_Refresh);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIWebServiceErrorHandler
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::OnError(nsresult aStatus,
|
||||
const nsAString &aStatusMessage)
|
||||
{
|
||||
DispatchEvent(eEvent_LinkException);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// nsIDOMEventListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNSUIEvent> evt = do_QueryInterface(aEvent);
|
||||
NS_ASSERTION(evt, "event should implement nsIDOMNSUIEvent");
|
||||
|
||||
PRBool defaultPrevented;
|
||||
evt->GetPreventDefault(&defaultPrevented);
|
||||
if (defaultPrevented)
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString type;
|
||||
aEvent->GetType(type);
|
||||
|
||||
if (type.EqualsLiteral("xforms-refresh")) {
|
||||
// refresh all of our form controls
|
||||
PRInt32 controlCount = mFormControls.Count();
|
||||
for (PRInt32 i = 0; i < controlCount; ++i) {
|
||||
NS_STATIC_CAST(nsXFormsControl*, mFormControls[i])->Refresh();
|
||||
}
|
||||
} else if (type.EqualsLiteral("xforms-revalidate")) {
|
||||
Revalidate();
|
||||
} else if (type.EqualsLiteral("xforms-recalculate")) {
|
||||
Recalculate();
|
||||
} else if (type.EqualsLiteral("xforms-rebuild")) {
|
||||
Rebuild();
|
||||
} else if (type.EqualsLiteral("xforms-reset")) {
|
||||
#ifdef DEBUG
|
||||
printf("nsXFormsModelElement::Reset()\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Load(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDocument> document = do_QueryInterface(target);
|
||||
if (document) {
|
||||
// The document has finished loading; that means that all of the models
|
||||
// in it are initialized. Fire the model-construct-done event to each
|
||||
// model.
|
||||
|
||||
nsVoidArray *models = NS_STATIC_CAST(nsVoidArray*,
|
||||
document->GetProperty(nsXFormsAtoms::modelListProperty));
|
||||
|
||||
NS_ASSERTION(models, "models list is empty!");
|
||||
for (PRInt32 i = 0; i < models->Count(); ++i) {
|
||||
NS_STATIC_CAST(nsXFormsModelElement*, models->ElementAt(i))
|
||||
->DispatchEvent(eEvent_ModelConstructDone);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::BeforeUnload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Unload(nsIDOMEvent* aEvent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Abort(nsIDOMEvent* aEvent)
|
||||
{
|
||||
DispatchEvent(eEvent_LinkException);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsModelElement::Error(nsIDOMEvent* aEvent)
|
||||
{
|
||||
DispatchEvent(eEvent_LinkException);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// internal methods
|
||||
|
||||
nsIDOMDocument*
|
||||
nsXFormsModelElement::FindInstanceDocument(const nsAString &aID)
|
||||
{
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
mElement->GetChildNodes(getter_AddRefs(children));
|
||||
|
||||
if (!children)
|
||||
return nsnull;
|
||||
|
||||
PRUint32 childCount = 0;
|
||||
children->GetLength(&childCount);
|
||||
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
nsCOMPtr<nsIDOMElement> element;
|
||||
nsAutoString id;
|
||||
|
||||
for (PRUint32 i = 0; i < childCount; ++i) {
|
||||
children->Item(i, getter_AddRefs(node));
|
||||
NS_ASSERTION(node, "incorrect NodeList length?");
|
||||
|
||||
element = do_QueryInterface(node);
|
||||
if (!element)
|
||||
continue;
|
||||
|
||||
element->GetAttribute(NS_LITERAL_STRING("id"), id);
|
||||
if (aID.IsEmpty() || aID.Equals(id)) {
|
||||
// make sure this is an xforms instance element
|
||||
nsAutoString namespaceURI, localName;
|
||||
element->GetNamespaceURI(namespaceURI);
|
||||
element->GetLocalName(localName);
|
||||
|
||||
if (localName.EqualsLiteral("instance") &&
|
||||
namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
|
||||
|
||||
// This is the requested instance, so get its document.
|
||||
nsCOMPtr<nsIXTFPrivate> xtfPriv = do_QueryInterface(element);
|
||||
NS_ENSURE_TRUE(xtfPriv, nsnull);
|
||||
|
||||
nsCOMPtr<nsISupports> instanceInner;
|
||||
xtfPriv->GetInner(getter_AddRefs(instanceInner));
|
||||
NS_ENSURE_TRUE(instanceInner, nsnull);
|
||||
|
||||
nsISupports *isupp = NS_STATIC_CAST(nsISupports*, instanceInner.get());
|
||||
nsXFormsInstanceElement *instance =
|
||||
NS_STATIC_CAST(nsXFormsInstanceElement*,
|
||||
NS_STATIC_CAST(nsIXTFGenericElement*, isupp));
|
||||
|
||||
return instance->GetDocument();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsModelElement::FinishConstruction()
|
||||
{
|
||||
// 3. if applicable, initialize P3P
|
||||
|
||||
// 4. construct instance data from initial instance data. apply all
|
||||
// <bind> elements in document order.
|
||||
|
||||
// we get the instance data from our instance child nodes
|
||||
|
||||
nsIDOMDocument *firstInstanceDoc = FindInstanceDocument(EmptyString());
|
||||
if (!firstInstanceDoc)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMElement> firstInstanceRoot;
|
||||
firstInstanceDoc->GetDocumentElement(getter_AddRefs(firstInstanceRoot));
|
||||
|
||||
nsCOMPtr<nsIDOMXPathEvaluator> xpath = do_QueryInterface(firstInstanceDoc);
|
||||
|
||||
nsCOMPtr<nsIDOMNodeList> children;
|
||||
mElement->GetChildNodes(getter_AddRefs(children));
|
||||
|
||||
PRUint32 childCount = 0;
|
||||
if (children)
|
||||
children->GetLength(&childCount);
|
||||
|
||||
nsAutoString namespaceURI, localName;
|
||||
|
||||
for (PRUint32 i = 0; i < childCount; ++i) {
|
||||
nsCOMPtr<nsIDOMNode> child;
|
||||
children->Item(i, getter_AddRefs(child));
|
||||
NS_ASSERTION(child, "there can't be null items in the NodeList!");
|
||||
|
||||
child->GetLocalName(localName);
|
||||
if (localName.EqualsLiteral("bind")) {
|
||||
child->GetNamespaceURI(namespaceURI);
|
||||
if (namespaceURI.EqualsLiteral(NS_NAMESPACE_XFORMS)) {
|
||||
if (!ProcessBind(xpath, firstInstanceRoot,
|
||||
nsCOMPtr<nsIDOMElement>(do_QueryInterface(child)))) {
|
||||
DispatchEvent(eEvent_BindingException);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 5. dispatch xforms-rebuild, xforms-recalculate, xforms-revalidate
|
||||
|
||||
// First hook up our event listener so we invoke the default action for
|
||||
// these events. We listen on the system event group so that we can check
|
||||
// whether preventDefault() was called by any content listeners.
|
||||
|
||||
nsCOMPtr<nsIDOMEventReceiver> receiver = do_QueryInterface(mElement);
|
||||
NS_ASSERTION(receiver, "xml elements must be event receivers");
|
||||
|
||||
nsCOMPtr<nsIDOMEventGroup> systemGroup;
|
||||
receiver->GetSystemEventGroup(getter_AddRefs(systemGroup));
|
||||
NS_ASSERTION(systemGroup, "system event group must exist");
|
||||
|
||||
nsCOMPtr<nsIDOM3EventTarget> targ = do_QueryInterface(mElement);
|
||||
for (unsigned int j = 0; j < NS_ARRAY_LENGTH(sModelEvents); ++j) {
|
||||
targ->AddGroupedEventListener(NS_ConvertUTF8toUTF16(sModelEvents[j].name),
|
||||
this, PR_FALSE, systemGroup);
|
||||
}
|
||||
|
||||
DispatchEvent(eEvent_Rebuild);
|
||||
DispatchEvent(eEvent_Recalculate);
|
||||
DispatchEvent(eEvent_Revalidate);
|
||||
|
||||
// We're done initializing this model.
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ReleaseExpr(void *aElement,
|
||||
nsIAtom *aPropertyName,
|
||||
void *aPropertyValue,
|
||||
void *aData)
|
||||
{
|
||||
nsIDOMXPathExpression *expr = NS_STATIC_CAST(nsIDOMXPathExpression*,
|
||||
aPropertyValue);
|
||||
|
||||
NS_RELEASE(expr);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsModelElement::ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
|
||||
nsIDOMNode *aContextNode,
|
||||
nsIDOMElement *aBindElement)
|
||||
{
|
||||
// Get the expression for the nodes that this <bind> applies to.
|
||||
nsAutoString expr;
|
||||
aBindElement->GetAttribute(NS_LITERAL_STRING("nodeset"), expr);
|
||||
if (expr.IsEmpty())
|
||||
return PR_TRUE;
|
||||
|
||||
nsCOMPtr<nsIDOMXPathNSResolver> resolver;
|
||||
aEvaluator->CreateNSResolver(aBindElement, getter_AddRefs(resolver));
|
||||
|
||||
// Get the model item properties specified by this <bind>.
|
||||
nsCOMPtr<nsIDOMXPathExpression> props[eModel__count];
|
||||
nsAutoString exprStrings[eModel__count];
|
||||
PRInt32 propCount = 0;
|
||||
nsresult rv = NS_OK;
|
||||
nsAutoString attrStr;
|
||||
|
||||
for (int i = 0; i < eModel__count; ++i) {
|
||||
sModelPropsList[i]->ToString(attrStr);
|
||||
|
||||
aBindElement->GetAttribute(attrStr, exprStrings[i]);
|
||||
if (!exprStrings[i].IsEmpty()) {
|
||||
rv = aEvaluator->CreateExpression(exprStrings[i], resolver,
|
||||
getter_AddRefs(props[i]));
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
++propCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (propCount == 0)
|
||||
return PR_TRUE; // successful, but nothing to do
|
||||
|
||||
nsCOMPtr<nsIDOMXPathResult> result;
|
||||
rv = aEvaluator->Evaluate(expr, aContextNode, resolver,
|
||||
nsIDOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
|
||||
nsnull, getter_AddRefs(result));
|
||||
if (NS_FAILED(rv))
|
||||
return PR_FALSE;
|
||||
|
||||
PRUint32 snapLen;
|
||||
rv = result->GetSnapshotLength(&snapLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsXFormsMDGSet set;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
PRInt32 contextPosition = 1;
|
||||
for (PRUint32 snapItem = 0; snapItem < snapLen; ++snapItem) {
|
||||
rv = result->SnapshotItem(snapItem, getter_AddRefs(node));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
if (!node) {
|
||||
NS_WARNING("nsXFormsModelElement::ProcessBind(): Empty node in result set.");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsXFormsXPathParser parser;
|
||||
nsXFormsXPathAnalyzer analyzer(aEvaluator, resolver);
|
||||
|
||||
// We must check whether the properties already exist on the node.
|
||||
for (int j = 0; j < eModel__count; ++j) {
|
||||
if (props[j]) {
|
||||
nsCOMPtr<nsIContent> content = do_QueryInterface(node, &rv);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("nsXFormsModelElement::ProcessBind(): Node is not IContent!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsIDOMXPathExpression *expr = props[j];
|
||||
NS_ADDREF(expr);
|
||||
|
||||
// Set property
|
||||
rv = content->SetProperty(sModelPropsList[j], expr, ReleaseExpr);
|
||||
if (rv == NS_PROPTABLE_PROP_OVERWRITTEN) {
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
// Get node dependencies
|
||||
nsAutoPtr<nsXFormsXPathNode> xNode(parser.Parse(exprStrings[j]));
|
||||
set.Clear();
|
||||
rv = analyzer.Analyze(node, xNode, expr, &exprStrings[j], &set);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Insert into MDG
|
||||
rv = mMDG.AddMIP((ModelItemPropName) j, expr, &set, parser.UsesDynamicFunc(),
|
||||
node, contextPosition++, snapLen);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsModelElement::DispatchEvent(nsXFormsModelEvent aEvent)
|
||||
{
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
mElement->GetOwnerDocument(getter_AddRefs(domDoc));
|
||||
|
||||
nsCOMPtr<nsIDOMDocumentEvent> doc = do_QueryInterface(domDoc);
|
||||
|
||||
nsCOMPtr<nsIDOMEvent> event;
|
||||
doc->CreateEvent(NS_LITERAL_STRING("Events"), getter_AddRefs(event));
|
||||
NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
|
||||
|
||||
const EventData *data = &sModelEvents[aEvent];
|
||||
event->InitEvent(NS_ConvertUTF8toUTF16(data->name),
|
||||
data->canBubble, data->canCancel);
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mElement);
|
||||
PRBool cancelled;
|
||||
return target->DispatchEvent(event, &cancelled);
|
||||
}
|
||||
|
||||
already_AddRefed<nsISchemaType>
|
||||
nsXFormsModelElement::GetTypeForControl(nsXFormsControl *aControl)
|
||||
{
|
||||
return nsnull;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsModelElement::AddFormControl(nsXFormsControl *aControl)
|
||||
{
|
||||
if (mFormControls.IndexOf(aControl) == -1)
|
||||
mFormControls.AppendElement(aControl);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsModelElement::RemoveFormControl(nsXFormsControl *aControl)
|
||||
{
|
||||
mFormControls.RemoveElement(aControl);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsModelElement::RemovePendingInstance()
|
||||
{
|
||||
--mPendingInstanceCount;
|
||||
if (IsComplete()) {
|
||||
nsresult rv = FinishConstruction();
|
||||
if (NS_SUCCEEDED(rv))
|
||||
DispatchEvent(eEvent_Refresh);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsXFormsModelElement::Startup()
|
||||
{
|
||||
sModelPropsList[eModel_type] = nsXFormsAtoms::type;
|
||||
sModelPropsList[eModel_readonly] = nsXFormsAtoms::readonly;
|
||||
sModelPropsList[eModel_required] = nsXFormsAtoms::required;
|
||||
sModelPropsList[eModel_relevant] = nsXFormsAtoms::relevant;
|
||||
sModelPropsList[eModel_calculate] = nsXFormsAtoms::calculate;
|
||||
sModelPropsList[eModel_constraint] = nsXFormsAtoms::constraint;
|
||||
sModelPropsList[eModel_p3ptype] = nsXFormsAtoms::p3ptype;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewXFormsModelElement(nsIXTFElement **aResult)
|
||||
{
|
||||
*aResult = new nsXFormsModelElement();
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,146 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsXFormsModelElement_h_
|
||||
#define nsXFormsModelElement_h_
|
||||
|
||||
#include "nsIXTFGenericElement.h"
|
||||
#include "nsIXTFPrivate.h"
|
||||
#include "nsIXFormsModelElement.h"
|
||||
#include "nsISchema.h"
|
||||
#include "nsCOMArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIDOMLoadListener.h"
|
||||
#include "nsIDOMDocument.h"
|
||||
#include "nsXFormsMDG.h"
|
||||
#include "nsXFormsElement.h"
|
||||
|
||||
#include "nsISchemaLoader.h"
|
||||
#include "nsISchema.h"
|
||||
|
||||
class nsIDOMElement;
|
||||
class nsIDOMNode;
|
||||
class nsIDOMXPathEvaluator;
|
||||
class nsXFormsControl;
|
||||
class nsXFormsInstanceElement;
|
||||
|
||||
enum nsXFormsModelEvent {
|
||||
eEvent_ModelConstruct,
|
||||
eEvent_ModelConstructDone,
|
||||
eEvent_Ready,
|
||||
eEvent_ModelDestruct,
|
||||
eEvent_Rebuild,
|
||||
eEvent_Refresh,
|
||||
eEvent_Revalidate,
|
||||
eEvent_Recalculate,
|
||||
eEvent_Reset,
|
||||
eEvent_BindingException,
|
||||
eEvent_LinkException,
|
||||
eEvent_LinkError,
|
||||
eEvent_ComputeExeception
|
||||
};
|
||||
|
||||
class nsXFormsModelElement : public nsXFormsElement,
|
||||
public nsIXTFGenericElement,
|
||||
public nsIXTFPrivate,
|
||||
public nsIXFormsModelElement,
|
||||
public nsISchemaLoadListener,
|
||||
public nsIDOMLoadListener
|
||||
{
|
||||
public:
|
||||
nsXFormsModelElement() NS_HIDDEN;
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIXTFELEMENT
|
||||
NS_DECL_NSIXTFGENERICELEMENT
|
||||
NS_DECL_NSIXTFPRIVATE
|
||||
NS_DECL_NSIXFORMSMODELELEMENT
|
||||
NS_DECL_NSISCHEMALOADLISTENER
|
||||
NS_DECL_NSIWEBSERVICEERRORHANDLER
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
// nsIDOMLoadListener
|
||||
NS_IMETHOD Load(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD BeforeUnload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Unload(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Abort(nsIDOMEvent* aEvent);
|
||||
NS_IMETHOD Error(nsIDOMEvent* aEvent);
|
||||
|
||||
NS_HIDDEN_(nsresult) DispatchEvent(nsXFormsModelEvent aEvent);
|
||||
|
||||
NS_HIDDEN_(already_AddRefed<nsISchemaType>)
|
||||
GetTypeForControl(nsXFormsControl *aControl);
|
||||
|
||||
NS_HIDDEN_(void) AddFormControl(nsXFormsControl *aControl);
|
||||
NS_HIDDEN_(void) RemoveFormControl(nsXFormsControl *aControl);
|
||||
|
||||
NS_HIDDEN_(void) AddPendingInstance() { ++mPendingInstanceCount; }
|
||||
NS_HIDDEN_(void) RemovePendingInstance();
|
||||
|
||||
NS_HIDDEN_(nsIDOMDocument*) FindInstanceDocument(const nsAString &aID);
|
||||
|
||||
// Called after nsXFormsAtoms is registered
|
||||
static NS_HIDDEN_(void) Startup();
|
||||
|
||||
private:
|
||||
class ModelItemProperties;
|
||||
|
||||
NS_HIDDEN_(nsresult) FinishConstruction();
|
||||
NS_HIDDEN_(PRBool) ProcessBind(nsIDOMXPathEvaluator *aEvaluator,
|
||||
nsIDOMNode *aContextNode,
|
||||
nsIDOMElement *aBindElement);
|
||||
|
||||
NS_HIDDEN_(void) RemoveModelFromDocument();
|
||||
|
||||
PRBool IsComplete() const { return (mSchemas.Count() == mSchemaCount
|
||||
&& mPendingInstanceCount == 0); }
|
||||
|
||||
nsIDOMElement *mElement;
|
||||
nsCOMArray<nsISchema> mSchemas;
|
||||
nsVoidArray mFormControls;
|
||||
|
||||
PRInt32 mSchemaCount;
|
||||
PRInt32 mPendingInstanceCount;
|
||||
|
||||
nsXFormsMDG mMDG;
|
||||
};
|
||||
|
||||
NS_HIDDEN_(nsresult) NS_NewXFormsModelElement(nsIXTFElement **aResult);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsIGenericFactory.h"
|
||||
#include "nsXFormsElementFactory.h"
|
||||
#include "nsXFormsAtoms.h"
|
||||
#include "nsXFormsModelElement.h"
|
||||
|
||||
NS_GENERIC_FACTORY_CONSTRUCTOR(nsXFormsElementFactory)
|
||||
|
||||
static const nsModuleComponentInfo components[] = {
|
||||
{ "XForms element factory",
|
||||
NS_XFORMSELEMENTFACTORY_CID,
|
||||
NS_XTF_ELEMENT_FACTORY_CONTRACTID_PREFIX NS_NAMESPACE_XFORMS,
|
||||
nsXFormsElementFactoryConstructor }
|
||||
};
|
||||
|
||||
PR_STATIC_CALLBACK(nsresult)
|
||||
XFormsModuleCtor(nsIModule* aSelf)
|
||||
{
|
||||
nsXFormsAtoms::InitAtoms();
|
||||
nsXFormsModelElement::Startup();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMPL_NSGETMODULE_WITH_CTOR(xforms, components, XFormsModuleCtor)
|
|
@ -0,0 +1,187 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsStubElement.h"
|
||||
#include "nsIDOMElement.h"
|
||||
#include "nsIDOMEventTarget.h"
|
||||
#include "nsIDOM3Node.h"
|
||||
#include "nsMemory.h"
|
||||
|
||||
static const nsIID sScriptingIIDs[] = {
|
||||
NS_IDOMELEMENT_IID,
|
||||
NS_IDOMEVENTTARGET_IID,
|
||||
NS_IDOM3NODE_IID
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS2(nsXFormsStubElement, nsIXTFElement, nsIXTFGenericElement)
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::OnDestroyed()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::GetElementType(PRUint32 *aElementType)
|
||||
{
|
||||
*aElementType = nsIXTFElement::ELEMENT_TYPE_GENERIC_ELEMENT;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::GetIsAttributeHandler(PRBool *aIsAttributeHandler)
|
||||
{
|
||||
*aIsAttributeHandler = PR_FALSE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::GetScriptingInterfaces(PRUint32 *aCount, nsIID ***aArray)
|
||||
{
|
||||
return CloneScriptingInterfaces(sScriptingIIDs,
|
||||
NS_ARRAY_LENGTH(sScriptingIIDs),
|
||||
aCount, aArray);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::WillChangeDocument(nsIDOMDocument *aNewDocument)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::DocumentChanged(nsIDOMDocument *aNewDocument)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::WillChangeParent(nsIDOMElement *aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::ParentChanged(nsIDOMElement *aNewParent)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::WillInsertChild(nsIDOMNode *aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::ChildInserted(nsIDOMNode *aChild, PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::WillAppendChild(nsIDOMNode *aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::ChildAppended(nsIDOMNode *aChild)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::WillRemoveChild(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::ChildRemoved(PRUint32 aIndex)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::WillSetAttribute(nsIAtom *aName,
|
||||
const nsAString &aNewValue)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::AttributeSet(nsIAtom *aName, const nsAString &aNewValue)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::WillRemoveAttribute(nsIAtom *aName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::AttributeRemoved(nsIAtom *aName)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::DoneAddingChildren()
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsXFormsStubElement::OnCreated(nsIXTFGenericElementWrapper *aWrapper)
|
||||
{
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
NS_NewXFormsStubElement(nsIXTFElement **aResult)
|
||||
{
|
||||
*aResult = new nsXFormsStubElement();
|
||||
if (!*aResult)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsXFormsStubElement_h_
|
||||
#define nsXFormsStubElement_h_
|
||||
|
||||
#include "nsIXTFGenericElement.h"
|
||||
#include "nsXFormsElement.h"
|
||||
|
||||
class nsXFormsStubElement : public nsXFormsElement,
|
||||
public nsIXTFGenericElement
|
||||
{
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIXTFELEMENT
|
||||
NS_DECL_NSIXTFGENERICELEMENT
|
||||
};
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsStubElement(nsIXTFElement **aResult);
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,95 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Darin Fisher <darin@meer.net>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef nsXFormsSubmissionElement_h_
|
||||
#define nsXFormsSubmissionElement_h_
|
||||
|
||||
#include "nsIXTFGenericElement.h"
|
||||
#include "nsIDOMEventListener.h"
|
||||
#include "nsXFormsElement.h"
|
||||
|
||||
class nsIMultiplexInputStream;
|
||||
class nsIInputStream;
|
||||
class nsIDOMElement;
|
||||
class nsIFile;
|
||||
class nsCString;
|
||||
class nsString;
|
||||
|
||||
class SubmissionAttachmentArray;
|
||||
|
||||
class nsXFormsSubmissionElement : public nsXFormsElement,
|
||||
public nsIXTFGenericElement,
|
||||
public nsIDOMEventListener
|
||||
{
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIXTFELEMENT
|
||||
NS_DECL_NSIXTFGENERICELEMENT
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
|
||||
nsXFormsSubmissionElement()
|
||||
: mElement(nsnull)
|
||||
{}
|
||||
|
||||
NS_HIDDEN_(void) Submit();
|
||||
NS_HIDDEN_(nsresult) SubmitEnd(PRBool succeeded);
|
||||
NS_HIDDEN_(PRBool) GetBooleanAttr(const nsAString &attrName, PRBool defaultVal = PR_FALSE);
|
||||
NS_HIDDEN_(void) GetDefaultInstanceData(nsIDOMNode **result);
|
||||
NS_HIDDEN_(nsresult) GetSelectedInstanceData(nsIDOMNode **result);
|
||||
NS_HIDDEN_(nsresult) SerializeData(nsIDOMNode *data, PRUint32 format, nsCString &uri, nsIInputStream **, nsCString &contentType);
|
||||
NS_HIDDEN_(nsresult) SerializeDataXML(nsIDOMNode *data, PRUint32 format, nsIInputStream **, nsCString &contentType, SubmissionAttachmentArray *);
|
||||
NS_HIDDEN_(nsresult) CreateSubmissionDoc(nsIDOMDocument *source, const nsString &encoding, SubmissionAttachmentArray *, nsIDOMDocument **result);
|
||||
NS_HIDDEN_(nsresult) CopyChildren(nsIDOMNode *source, nsIDOMNode *dest, nsIDOMDocument *destDoc, SubmissionAttachmentArray *, const nsString &cdataElements, PRBool indent, PRUint32 depth);
|
||||
NS_HIDDEN_(nsresult) SerializeDataURLEncoded(nsIDOMNode *data, PRUint32 format, nsCString &uri, nsIInputStream **, nsCString &contentType);
|
||||
NS_HIDDEN_(void) AppendURLEncodedData(nsIDOMNode *data, const nsCString &sep, nsCString &buf);
|
||||
NS_HIDDEN_(nsresult) SerializeDataMultipartRelated(nsIDOMNode *data, PRUint32 format, nsIInputStream **, nsCString &contentType);
|
||||
NS_HIDDEN_(nsresult) SerializeDataMultipartFormData(nsIDOMNode *data, PRUint32 format, nsIInputStream **, nsCString &contentType);
|
||||
NS_HIDDEN_(nsresult) AppendMultipartFormData(nsIDOMNode *data, const nsCString &boundary, nsCString &buf, nsIMultiplexInputStream *);
|
||||
NS_HIDDEN_(nsresult) AppendPostDataChunk(nsCString &postDataChunk, nsIMultiplexInputStream *multiStream);
|
||||
NS_HIDDEN_(nsresult) GetElementEncodingType(nsIDOMNode *data, PRUint32 *encType);
|
||||
NS_HIDDEN_(nsresult) CreateFileStream(const nsString &absURI, nsIFile **file, nsIInputStream **stream);
|
||||
NS_HIDDEN_(nsresult) SendData(PRUint32 format, const nsCString &uri, nsIInputStream *stream, const nsCString &contentType);
|
||||
|
||||
private:
|
||||
nsIDOMElement *mElement;
|
||||
};
|
||||
|
||||
NS_HIDDEN_(nsresult)
|
||||
NS_NewXFormsSubmissionElement(nsIXTFElement **aResult);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* IBM Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Brian Ryner <bryner@brianryner.com>
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef __NSXFORMSTYPES_H__
|
||||
#define __NSXFORMSTYPES_H__
|
||||
|
||||
enum ModelItemPropName
|
||||
{
|
||||
eModel_type,
|
||||
eModel_readonly,
|
||||
eModel_required,
|
||||
eModel_relevant,
|
||||
eModel_calculate,
|
||||
eModel_constraint,
|
||||
eModel_p3ptype,
|
||||
eModel__count
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,198 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsXPathAnalyzer.h"
|
||||
#include "nsIDOMXPathResult.h"
|
||||
|
||||
#ifdef DEBUG
|
||||
// #define DEBUG_XF_ANALYZER
|
||||
#endif
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathAnalyzer)
|
||||
|
||||
nsXFormsXPathAnalyzer::nsXFormsXPathAnalyzer(nsIDOMXPathEvaluator* aEvaluator, nsIDOMXPathNSResolver* aResolver)
|
||||
: mEvaluator(aEvaluator), mResolver(aResolver)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsXPathAnalyzer);
|
||||
}
|
||||
|
||||
nsXFormsXPathAnalyzer::~nsXFormsXPathAnalyzer()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXFormsXPathAnalyzer);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsXFormsXPathAnalyzer::Analyze(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
|
||||
nsIDOMXPathExpression* aExpression, const nsAString* aExprString,
|
||||
nsXFormsMDGSet* aSet)
|
||||
{
|
||||
NS_ENSURE_TRUE(aContextNode, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(aNode, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(aExpression, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(aExprString, NS_ERROR_INVALID_ARG);
|
||||
NS_ENSURE_TRUE(aSet, NS_ERROR_INVALID_ARG);
|
||||
|
||||
mCurExpression = aExpression;
|
||||
mCurExprString = aExprString;
|
||||
mCurSet = aSet;
|
||||
|
||||
#ifdef DEBUG_XF_ANALYZER
|
||||
printf("=====================================\n");
|
||||
printf("Analyzing: %s\n", NS_ConvertUCS2toUTF8(*mCurExprString).get());
|
||||
printf("=====================================\n");
|
||||
#endif
|
||||
|
||||
nsresult rv = AnalyzeRecursively(aContextNode, aNode->mChild, 0);
|
||||
#ifdef DEBUG_XF_ANALYZER
|
||||
printf("-------------------------------------\n");
|
||||
#endif
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
nsresult
|
||||
nsXFormsXPathAnalyzer::AnalyzeRecursively(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
|
||||
PRUint32 aIndent)
|
||||
{
|
||||
nsXFormsXPathNode* t;
|
||||
nsAutoString xp;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIDOMXPathResult> result;
|
||||
nsCOMPtr<nsIDOMNode> node;
|
||||
char strbuf[100];
|
||||
char* strpos;
|
||||
|
||||
#ifdef DEBUG_beaufour_xxx
|
||||
printf("nsXFormsXPathParser::AnalyzeRecursively(%p)\n", (void*) aNode);
|
||||
#endif
|
||||
|
||||
for (; aNode; aNode = aNode->mSibling) {
|
||||
#ifdef DEBUG_beaufour_xxx
|
||||
printf("\tChild: %p, Sibling: %p\n", (void*) aNode->mChild, (void*) aNode->mSibling);
|
||||
printf("\tIndex: %d - %d\n", aNode->mStartIndex, aNode->mEndIndex);
|
||||
printf("\tCon: %d, Predicate: %d, Literal: %d\n", aNode->mCon, aNode->mPredicate, aNode->mLiteral);
|
||||
#endif
|
||||
|
||||
if ( aNode->mEndIndex < 0
|
||||
|| aNode->mStartIndex >= aNode->mEndIndex
|
||||
|| ((PRUint32) aNode->mEndIndex == mCurExprString->Length() && aNode->mStartIndex == 0)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
PRBool hasContinue = PR_FALSE;
|
||||
strpos = strbuf;
|
||||
*strpos = '\0';
|
||||
|
||||
// hasContinue == whether we have a child with a mCon
|
||||
t = aNode->mChild;
|
||||
while (t && !hasContinue) {
|
||||
hasContinue = t->mCon;
|
||||
t = t->mSibling;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XF_ANALYZER
|
||||
for (PRUint32 j = 0; j < aIndent; ++j) {
|
||||
strpos += sprintf(strpos, " ");
|
||||
}
|
||||
|
||||
strpos += sprintf(strpos, "<%s> ", hasContinue ? "C" : " ");
|
||||
|
||||
if (aNode->mPredicate) {
|
||||
if (!(aNode->mChild)) {
|
||||
strpos += sprintf(strpos, "[PredicateVal], ");
|
||||
} else {
|
||||
strpos += sprintf(strpos, "[Predicate], ");
|
||||
}
|
||||
} else {
|
||||
if (!(aNode->mChild)) {
|
||||
strpos += sprintf(strpos, "[AxisStepsVal], ");
|
||||
} else {
|
||||
if (!hasContinue) {
|
||||
strpos += printf(strpos, "[AxisSteps], ");
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (aNode->mCon) {
|
||||
// Remove the leading /
|
||||
xp = Substring(*mCurExprString, aNode->mStartIndex + 1, aNode->mEndIndex - aNode->mStartIndex + 1);
|
||||
} else {
|
||||
xp = Substring(*mCurExprString, aNode->mStartIndex, aNode->mEndIndex - aNode->mStartIndex);
|
||||
}
|
||||
|
||||
rv = mEvaluator->Evaluate(xp, aContextNode, mResolver,
|
||||
nsIDOMXPathResult::ANY_TYPE,
|
||||
nsnull, getter_AddRefs(result));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
PRUint16 type;
|
||||
rv = result->GetResultType(&type);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We are only interested in nodes
|
||||
if ( type != nsIDOMXPathResult::UNORDERED_NODE_ITERATOR_TYPE
|
||||
&& type != nsIDOMXPathResult::ORDERED_NODE_ITERATOR_TYPE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
while (NS_SUCCEEDED(result->IterateNext(getter_AddRefs(node))) && node) {
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
#ifdef DEBUG_XF_ANALYZER
|
||||
printf(strbuf);
|
||||
#endif
|
||||
if (aNode->mChild || (!aNode->mChild && hasContinue)) {
|
||||
#ifdef DEBUG_XF_ANALYZER
|
||||
printf("iterating '%s'\n", NS_ConvertUCS2toUTF8(xp).get());
|
||||
#endif
|
||||
} else {
|
||||
#ifdef DEBUG_XF_ANALYZER
|
||||
printf("collecting '%s'\n", NS_ConvertUCS2toUTF8(xp).get());
|
||||
#endif
|
||||
mCurSet->AddNode(node);
|
||||
}
|
||||
rv = AnalyzeRecursively(node, aNode->mChild, aIndent + 1);
|
||||
}
|
||||
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nscore.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsXFormsXPathNode.h"
|
||||
#include "nsIDOMXPathExpression.h"
|
||||
#include "nsIDOMXPathEvaluator.h"
|
||||
#include "nsIDOMXPathNSResolver.h"
|
||||
#include "nsXFormsMDGSet.h"
|
||||
#include "nsIDOMNode.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
|
||||
/**
|
||||
* This class analyzes an XPath Expression parse tree (nsXFormsXPathNode), and
|
||||
* returns all the nodes that the expression depends on.
|
||||
*
|
||||
* @note Should be reimplemented and moved to Transformiix
|
||||
* @note This class is not thread safe (mCur.*)
|
||||
*/
|
||||
class nsXFormsXPathAnalyzer {
|
||||
private:
|
||||
nsCOMPtr<nsIDOMXPathEvaluator> mEvaluator;
|
||||
nsCOMPtr<nsIDOMXPathNSResolver> mResolver;
|
||||
|
||||
nsXFormsMDGSet* mCurSet;
|
||||
nsCOMPtr<nsIDOMXPathExpression> mCurExpression;
|
||||
const nsAString* mCurExprString;
|
||||
|
||||
nsresult AnalyzeRecursively(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
|
||||
PRUint32 aIndent);
|
||||
|
||||
public:
|
||||
nsXFormsXPathAnalyzer(nsIDOMXPathEvaluator* aEvaluator, nsIDOMXPathNSResolver* aResolver);
|
||||
~nsXFormsXPathAnalyzer();
|
||||
|
||||
nsresult Analyze(nsIDOMNode* aContextNode, const nsXFormsXPathNode* aNode,
|
||||
nsIDOMXPathExpression* aExpression, const nsAString* aExprString,
|
||||
nsXFormsMDGSet* aSet);
|
||||
};
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsXPathNode.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathNode)
|
||||
|
||||
nsXFormsXPathNode::nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue)
|
||||
: mChild(nsnull), mEndIndex(-100), mCon(aContinue)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsXPathNode);
|
||||
|
||||
if (aParent) {
|
||||
mSibling = aParent->mChild;
|
||||
aParent->mChild = this;
|
||||
} else {
|
||||
mSibling = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
nsXFormsXPathNode::~nsXFormsXPathNode()
|
||||
{
|
||||
delete mChild;
|
||||
delete mSibling;
|
||||
|
||||
MOZ_COUNT_DTOR(nsXFormsXPathNode);
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
#ifndef __NSXFORMSXPATHNODE_H__
|
||||
#define __NSXFORMSXPATHNODE_H__
|
||||
|
||||
#include "nscore.h"
|
||||
|
||||
/**
|
||||
* The node type of the XPath Expression parse tree that nsXFormsXPathParser
|
||||
* creates.
|
||||
*
|
||||
* @note Should be reimplemented and moved to Transformiix
|
||||
*/
|
||||
class nsXFormsXPathNode {
|
||||
public:
|
||||
nsXFormsXPathNode* mChild;
|
||||
nsXFormsXPathNode* mSibling;
|
||||
PRInt32 mStartIndex;
|
||||
PRInt32 mEndIndex;
|
||||
PRBool mCon;
|
||||
PRBool mPredicate;
|
||||
PRBool mLiteral;
|
||||
|
||||
nsXFormsXPathNode(nsXFormsXPathNode* aParent, PRBool aContinue = PR_FALSE);
|
||||
~nsXFormsXPathNode();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,911 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsXPathParser.h"
|
||||
#include "nscore.h"
|
||||
|
||||
/*
|
||||
* (TODO) GIANT hack. Without exceptions everything had to be rewritten, and
|
||||
* that was to overdo it a bit, when the code probably does not survive...
|
||||
*/
|
||||
void
|
||||
XPathCompilerException(const char* aMsg, nsAString& aExpression, PRInt32 aOffset = -1, PRInt32 aLength = -1) {
|
||||
printf("XPathCompilerException: %s, %s [o: %d, l: %d]\n",
|
||||
aMsg,
|
||||
NS_ConvertUCS2toUTF8(aExpression).get(), aOffset, aLength);
|
||||
|
||||
printf("WARNING: Houston we have a problem, and unlike Apollo 13, we're not going to make it!\n");
|
||||
NS_ABORT();
|
||||
}
|
||||
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathParser)
|
||||
|
||||
nsXFormsXPathParser::nsXFormsXPathParser()
|
||||
: mUsesDynamicFunc(PR_FALSE), mHead(nsnull), mAnalyzeStackPointer(nsnull)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsXPathParser);
|
||||
}
|
||||
|
||||
nsXFormsXPathParser::~nsXFormsXPathParser()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXFormsXPathParser);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::PushContext(PRInt32 aStartIndex)
|
||||
{
|
||||
mHead = new nsXFormsXPathNode(mHead);
|
||||
if (aStartIndex == -100) {
|
||||
mHead->mStartIndex = mScanner.Offset() + 1;
|
||||
} else {
|
||||
mHead->mStartIndex = aStartIndex;
|
||||
}
|
||||
mStack[++mAnalyzeStackPointer] = mHead;
|
||||
mHead->mPredicate = mPredicateLevel != 0;
|
||||
mHead->mLiteral = PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::PushContext(nsXFormsXPathNode* aNode)
|
||||
{
|
||||
mStack[++mAnalyzeStackPointer] = aNode;
|
||||
mHead = aNode;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::EndContext()
|
||||
{
|
||||
if (mHead) {
|
||||
mHead->mEndIndex = mScanner.Offset() + 1;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::RestartContext()
|
||||
{
|
||||
nsXFormsXPathNode* temp = new nsXFormsXPathNode(nsnull, PR_TRUE);
|
||||
temp->mStartIndex = mScanner.Offset() + 1;
|
||||
temp->mSibling = mHead->mChild;
|
||||
temp->mPredicate = mPredicateLevel != 0;
|
||||
mHead->mChild = temp;
|
||||
mHead = temp;
|
||||
mStack[mAnalyzeStackPointer] = mHead;
|
||||
}
|
||||
|
||||
nsXFormsXPathNode*
|
||||
nsXFormsXPathParser::JustContext()
|
||||
{
|
||||
nsXFormsXPathNode* t = mStack[mAnalyzeStackPointer];
|
||||
mHead = mStack[--mAnalyzeStackPointer];
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
nsXFormsXPathNode*
|
||||
nsXFormsXPathParser::PopContext()
|
||||
{
|
||||
if (mHead->mEndIndex == -100) {
|
||||
mHead->mEndIndex = mScanner.Offset() + 1;
|
||||
}
|
||||
|
||||
NS_ASSERTION(mHead->mStartIndex <= mHead->mEndIndex, "");
|
||||
NS_ASSERTION(mAnalyzeStackPointer - 1 >= 0, "");
|
||||
mHead = mStack[--mAnalyzeStackPointer];
|
||||
|
||||
return mHead;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::AbbreviatedStep()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::DOT:
|
||||
PopToken();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::DOTDOT:
|
||||
PopToken();
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Expected . or ..", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::AbsoluteLocationPath()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
nsXFormsXPathScanner::XPATHTOKEN r;
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::SLASH:
|
||||
PopToken();
|
||||
r = PeekToken();
|
||||
switch (r) {
|
||||
case nsXFormsXPathScanner::ANCESTOR:
|
||||
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
|
||||
case nsXFormsXPathScanner::ATTRIBUTE:
|
||||
case nsXFormsXPathScanner::CHILD:
|
||||
case nsXFormsXPathScanner::DESCENDANT:
|
||||
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
|
||||
case nsXFormsXPathScanner::FOLLOWING:
|
||||
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
|
||||
case nsXFormsXPathScanner::NAMESPACE:
|
||||
case nsXFormsXPathScanner::PARENT:
|
||||
case nsXFormsXPathScanner::PRECEDING:
|
||||
case nsXFormsXPathScanner::PRECEDING_SIBLING:
|
||||
case nsXFormsXPathScanner::SELF:
|
||||
case nsXFormsXPathScanner::AT:
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
case nsXFormsXPathScanner::PI:
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
case nsXFormsXPathScanner::DOT:
|
||||
case nsXFormsXPathScanner::DOTDOT:
|
||||
RelativeLocationPath();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::SLASHSLASH:
|
||||
PopToken();
|
||||
if (DoRelative()) {
|
||||
RelativeLocationPath();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Not an absolute location path", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::AdditiveExpression()
|
||||
{
|
||||
PRBool con = PR_TRUE;
|
||||
|
||||
MultiplicationExpr();
|
||||
|
||||
while (con) {
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::PLUS:
|
||||
PopToken();
|
||||
MultiplicationExpr();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::MINUS:
|
||||
PopToken();
|
||||
MultiplicationExpr();
|
||||
break;
|
||||
|
||||
default:
|
||||
con = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::AndExpr()
|
||||
{
|
||||
EqualityExpr();
|
||||
if (PeekToken() == nsXFormsXPathScanner::AND) {
|
||||
PopToken();
|
||||
AndExpr();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::AxisSpecifier()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::ANCESTOR:
|
||||
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
|
||||
case nsXFormsXPathScanner::ATTRIBUTE:
|
||||
case nsXFormsXPathScanner::CHILD:
|
||||
case nsXFormsXPathScanner::DESCENDANT:
|
||||
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
|
||||
case nsXFormsXPathScanner::FOLLOWING:
|
||||
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
|
||||
case nsXFormsXPathScanner::NAMESPACE:
|
||||
case nsXFormsXPathScanner::PARENT:
|
||||
case nsXFormsXPathScanner::PRECEDING:
|
||||
case nsXFormsXPathScanner::PRECEDING_SIBLING:
|
||||
case nsXFormsXPathScanner::SELF:
|
||||
PopToken();
|
||||
case nsXFormsXPathScanner::AT:
|
||||
PopToken();
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Not a axis specifier", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathParser::DoRelative()
|
||||
{
|
||||
PRBool ret = PR_FALSE;
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::ANCESTOR:
|
||||
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
|
||||
case nsXFormsXPathScanner::ATTRIBUTE:
|
||||
case nsXFormsXPathScanner::CHILD:
|
||||
case nsXFormsXPathScanner::DESCENDANT:
|
||||
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
|
||||
case nsXFormsXPathScanner::FOLLOWING:
|
||||
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
|
||||
case nsXFormsXPathScanner::NAMESPACE:
|
||||
case nsXFormsXPathScanner::PARENT:
|
||||
case nsXFormsXPathScanner::PRECEDING:
|
||||
case nsXFormsXPathScanner::PRECEDING_SIBLING:
|
||||
case nsXFormsXPathScanner::SELF:
|
||||
case nsXFormsXPathScanner::AT:
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
case nsXFormsXPathScanner::PI:
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
case nsXFormsXPathScanner::DOT:
|
||||
case nsXFormsXPathScanner::DOTDOT:
|
||||
ret = PR_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::EqualityExpr()
|
||||
{
|
||||
RelationalExpression();
|
||||
|
||||
PRBool con = PR_TRUE;
|
||||
while (con) {
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::EQUAL:
|
||||
PopToken();
|
||||
RelationalExpression();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::NOTEQUAL:
|
||||
PopToken();
|
||||
RelationalExpression();
|
||||
break;
|
||||
|
||||
default:
|
||||
con = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::Expr()
|
||||
{
|
||||
OrExpr();
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::FilterExpr()
|
||||
{
|
||||
if (PrimaryExpr() && PeekToken() == nsXFormsXPathScanner::LBRACK) {
|
||||
Predicate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::FunctionCall()
|
||||
{
|
||||
if (!mUsesDynamicFunc) {
|
||||
nsDependentSubstring fname = Substring(mScanner.Expression(), mScanner.Offset() + 1, mScanner.Offset() + mScanner.Length() + 1);
|
||||
if (fname.Equals(NS_LITERAL_STRING("now"))) {
|
||||
mUsesDynamicFunc = PR_TRUE;
|
||||
}
|
||||
}
|
||||
PopToken();
|
||||
PopToken();
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
|
||||
PRBool con = t == nsXFormsXPathScanner::RPARAN ? PR_FALSE : PR_TRUE;
|
||||
while (con) {
|
||||
if (t == nsXFormsXPathScanner::XPATHEOF) {
|
||||
XPathCompilerException("Expected ) got EOF", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
nsXFormsXPathNode* c = JustContext();
|
||||
Expr();
|
||||
PushContext(c);
|
||||
|
||||
t = PeekToken();
|
||||
if (t == nsXFormsXPathScanner::COMMA) {
|
||||
PopToken(); // Another Argument
|
||||
con = PR_TRUE;
|
||||
} else {
|
||||
con = PR_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (t != nsXFormsXPathScanner::RPARAN) {
|
||||
XPathCompilerException("Expected )", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
|
||||
PopToken();
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::LocationPath()
|
||||
{
|
||||
if (DoRelative()) {
|
||||
PushContext();
|
||||
RelativeLocationPath();
|
||||
PopContext();
|
||||
} else {
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::SLASH:
|
||||
case nsXFormsXPathScanner::SLASHSLASH:
|
||||
PushContext();
|
||||
AbsoluteLocationPath();
|
||||
PopContext();
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Not a location path", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::MultiplicationExpr()
|
||||
{
|
||||
UnaryExpr();
|
||||
PRBool con = PR_TRUE;
|
||||
while (con) {
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::MULTIPLYOPERATOR:
|
||||
case nsXFormsXPathScanner::DIV:
|
||||
case nsXFormsXPathScanner::MOD:
|
||||
PopToken();
|
||||
UnaryExpr();
|
||||
break;
|
||||
default:
|
||||
con = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::NameTest()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
PopToken();
|
||||
break;
|
||||
default:
|
||||
XPathCompilerException("NodeTest error", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::NodeTest()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
NameTest();
|
||||
break;
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
case nsXFormsXPathScanner::PI:
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
NodeType();
|
||||
break;
|
||||
default:
|
||||
XPathCompilerException("Not a node test", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::NodeType()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
PopToken();
|
||||
PopToken();
|
||||
PopToken();
|
||||
break;
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
PopToken();
|
||||
PopToken();
|
||||
PopToken();
|
||||
break;
|
||||
case nsXFormsXPathScanner::PI:
|
||||
PopToken();
|
||||
if ((t = PeekToken()) == nsXFormsXPathScanner::LPARAN) {
|
||||
PopToken();
|
||||
PopToken();
|
||||
PopToken();
|
||||
}
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
PopToken();
|
||||
PopToken();
|
||||
PopToken();
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Not a valid NodeType", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::OrExpr()
|
||||
{
|
||||
AndExpr();
|
||||
if (PeekToken() == nsXFormsXPathScanner::OR) {
|
||||
PopToken();
|
||||
OrExpr();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::PathExpr()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::ANCESTOR:
|
||||
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
|
||||
case nsXFormsXPathScanner::ATTRIBUTE:
|
||||
case nsXFormsXPathScanner::CHILD:
|
||||
case nsXFormsXPathScanner::DESCENDANT:
|
||||
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
|
||||
case nsXFormsXPathScanner::FOLLOWING:
|
||||
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
|
||||
case nsXFormsXPathScanner::NAMESPACE:
|
||||
case nsXFormsXPathScanner::PARENT:
|
||||
case nsXFormsXPathScanner::PRECEDING:
|
||||
case nsXFormsXPathScanner::PRECEDING_SIBLING:
|
||||
case nsXFormsXPathScanner::SELF:
|
||||
case nsXFormsXPathScanner::AT:
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
case nsXFormsXPathScanner::PI:
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
case nsXFormsXPathScanner::DOT:
|
||||
case nsXFormsXPathScanner::DOTDOT:
|
||||
case nsXFormsXPathScanner::SLASH:
|
||||
case nsXFormsXPathScanner::SLASHSLASH:
|
||||
LocationPath();
|
||||
break;
|
||||
|
||||
default:
|
||||
PushContext();
|
||||
FilterExpr();
|
||||
t = PeekToken();
|
||||
if (t == nsXFormsXPathScanner::SLASH || t == nsXFormsXPathScanner::SLASHSLASH) {
|
||||
PopToken();
|
||||
|
||||
if (DoRelative()) {
|
||||
RelativeLocationPath();
|
||||
} else {
|
||||
nsAutoString nullstr;
|
||||
XPathCompilerException("After / in a filter expression it is required to have a reletive path expression", nullstr);
|
||||
}
|
||||
|
||||
}
|
||||
PopContext();
|
||||
}
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathParser::PeekToken()
|
||||
{
|
||||
return mPeek;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathParser::PopToken()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN temp = mPeek;
|
||||
mPeek = mScanner.NextToken();
|
||||
if (mPeek == nsXFormsXPathScanner::WHITESPACE) { // Skip whitespaces
|
||||
mPeek = mScanner.NextToken();
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::Predicate()
|
||||
{
|
||||
EndContext();
|
||||
mPredicateLevel++;
|
||||
while (PeekToken() == nsXFormsXPathScanner::LBRACK) {
|
||||
PopToken();
|
||||
Expr();
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PopToken();
|
||||
if (t != nsXFormsXPathScanner::RBRACK) {
|
||||
XPathCompilerException("Expected ]", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
mPredicateLevel--;
|
||||
RestartContext();
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathParser::PrimaryExpr()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::VARIABLE:
|
||||
PopToken();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::LPARAN: {
|
||||
PopToken();
|
||||
nsXFormsXPathNode* c = JustContext();
|
||||
Expr();
|
||||
PushContext(c);
|
||||
if (PeekToken() == nsXFormsXPathScanner::RPARAN) {
|
||||
PopToken();
|
||||
} else {
|
||||
XPathCompilerException("Expected )", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::LITERAL:
|
||||
mHead->mLiteral = PR_TRUE;
|
||||
PopToken();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::NUMBER:
|
||||
mHead->mLiteral = PR_TRUE;
|
||||
PopToken();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::FUNCTIONNAME:
|
||||
FunctionCall();
|
||||
return PeekToken() == nsXFormsXPathScanner::SLASH || PeekToken() == nsXFormsXPathScanner::SLASHSLASH || PeekToken() == nsXFormsXPathScanner::LBRACK;
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Not a primary expression", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::RelationalExpression()
|
||||
{
|
||||
AdditiveExpression();
|
||||
PRBool con = PR_TRUE;
|
||||
while (con) {
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::LESS:
|
||||
PopToken();
|
||||
AdditiveExpression();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::LEQUAL:
|
||||
PopToken();
|
||||
AdditiveExpression();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::GREATER:
|
||||
PopToken();
|
||||
AdditiveExpression();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::GEQUAL:
|
||||
PopToken();
|
||||
AdditiveExpression();
|
||||
break;
|
||||
|
||||
default:
|
||||
con = PR_FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::RelativeLocationPath()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::ANCESTOR:
|
||||
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
|
||||
case nsXFormsXPathScanner::ATTRIBUTE:
|
||||
case nsXFormsXPathScanner::CHILD:
|
||||
case nsXFormsXPathScanner::DESCENDANT:
|
||||
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
|
||||
case nsXFormsXPathScanner::FOLLOWING:
|
||||
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
|
||||
case nsXFormsXPathScanner::NAMESPACE:
|
||||
case nsXFormsXPathScanner::PARENT:
|
||||
case nsXFormsXPathScanner::PRECEDING:
|
||||
case nsXFormsXPathScanner::PRECEDING_SIBLING:
|
||||
case nsXFormsXPathScanner::SELF:
|
||||
case nsXFormsXPathScanner::AT:
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
case nsXFormsXPathScanner::PI:
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
Step();
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::DOT:
|
||||
case nsXFormsXPathScanner::DOTDOT:
|
||||
AbbreviatedStep();
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Not a relative location path ", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
|
||||
t = PeekToken();
|
||||
|
||||
if (t == nsXFormsXPathScanner::SLASH || t == nsXFormsXPathScanner::SLASHSLASH) {
|
||||
PopToken();
|
||||
if (DoRelative()) {
|
||||
RelativeLocationPath();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::Step()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::ANCESTOR:
|
||||
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
|
||||
case nsXFormsXPathScanner::ATTRIBUTE:
|
||||
case nsXFormsXPathScanner::CHILD:
|
||||
case nsXFormsXPathScanner::DESCENDANT:
|
||||
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
|
||||
case nsXFormsXPathScanner::FOLLOWING:
|
||||
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
|
||||
case nsXFormsXPathScanner::NAMESPACE:
|
||||
case nsXFormsXPathScanner::PARENT:
|
||||
case nsXFormsXPathScanner::PRECEDING:
|
||||
case nsXFormsXPathScanner::PRECEDING_SIBLING:
|
||||
case nsXFormsXPathScanner::SELF:
|
||||
case nsXFormsXPathScanner::AT:
|
||||
AxisSpecifier();
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
case nsXFormsXPathScanner::PI:
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
NodeTest();
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Expected a NodeTest expression", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
|
||||
t = PeekToken();
|
||||
if (t == nsXFormsXPathScanner::LBRACK) {
|
||||
Predicate(); // set the predicates
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::UnaryExpr()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::MINUS:
|
||||
PopToken();
|
||||
UnaryExpr();
|
||||
break;
|
||||
|
||||
default:
|
||||
UnionExpr();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::UnionExpr()
|
||||
{
|
||||
nsXFormsXPathScanner::XPATHTOKEN t = PeekToken();
|
||||
switch (t) {
|
||||
case nsXFormsXPathScanner::ANCESTOR:
|
||||
case nsXFormsXPathScanner::ANCESTOR_OR_SELF:
|
||||
case nsXFormsXPathScanner::ATTRIBUTE:
|
||||
case nsXFormsXPathScanner::CHILD:
|
||||
case nsXFormsXPathScanner::DESCENDANT:
|
||||
case nsXFormsXPathScanner::DESCENDANT_OR_SELF:
|
||||
case nsXFormsXPathScanner::FOLLOWING:
|
||||
case nsXFormsXPathScanner::FOLLOWING_SIBLING:
|
||||
case nsXFormsXPathScanner::NAMESPACE:
|
||||
case nsXFormsXPathScanner::PARENT:
|
||||
case nsXFormsXPathScanner::PRECEDING:
|
||||
case nsXFormsXPathScanner::PRECEDING_SIBLING:
|
||||
case nsXFormsXPathScanner::SELF:
|
||||
case nsXFormsXPathScanner::AT:
|
||||
case nsXFormsXPathScanner::STAR:
|
||||
case nsXFormsXPathScanner::NCNAME:
|
||||
case nsXFormsXPathScanner::QNAME:
|
||||
case nsXFormsXPathScanner::COMMENT:
|
||||
case nsXFormsXPathScanner::TEXT:
|
||||
case nsXFormsXPathScanner::PI:
|
||||
case nsXFormsXPathScanner::NODE:
|
||||
case nsXFormsXPathScanner::DOT:
|
||||
case nsXFormsXPathScanner::DOTDOT:
|
||||
case nsXFormsXPathScanner::SLASH:
|
||||
case nsXFormsXPathScanner::SLASHSLASH:
|
||||
PathExpr();
|
||||
t = PeekToken();
|
||||
if (t == nsXFormsXPathScanner::UNION) {
|
||||
PopToken();
|
||||
UnionExpr();
|
||||
}
|
||||
break;
|
||||
|
||||
case nsXFormsXPathScanner::VARIABLE:
|
||||
case nsXFormsXPathScanner::LPARAN:
|
||||
case nsXFormsXPathScanner::LITERAL:
|
||||
case nsXFormsXPathScanner::NUMBER:
|
||||
case nsXFormsXPathScanner::FUNCTIONNAME:
|
||||
PathExpr();
|
||||
t = PeekToken();
|
||||
if (t == nsXFormsXPathScanner::UNION) {
|
||||
PopToken();
|
||||
UnionExpr();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
XPathCompilerException("Unexpected union token", mScanner.Expression(), mScanner.Offset(), mScanner.Length());
|
||||
}
|
||||
}
|
||||
|
||||
nsXFormsXPathNode*
|
||||
nsXFormsXPathParser::Parse(const nsAString& aExpression)
|
||||
{
|
||||
#ifdef DEBUG_XF_PARSER
|
||||
printf("=====================================\n");
|
||||
printf("Parsing: %s\n", NS_ConvertUCS2toUTF8(aExpression).get());
|
||||
printf("=====================================\n");
|
||||
#endif
|
||||
|
||||
mScanner.Init(aExpression);
|
||||
mAnalyzeStackPointer = 0;
|
||||
mPredicateLevel = 0;
|
||||
mHead = nsnull;
|
||||
PopToken();
|
||||
PushContext();
|
||||
|
||||
nsXFormsXPathNode* root = mHead;
|
||||
Expr();
|
||||
PopContext();
|
||||
|
||||
#ifdef DEBUG_XF_PARSER
|
||||
Dump(root);
|
||||
printf("-------------------------------------\n");
|
||||
#endif
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathParser::UsesDynamicFunc() const {
|
||||
return mUsesDynamicFunc;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_XF_PARSER
|
||||
void
|
||||
nsXFormsXPathParser::Dump(nsXFormsXPathNode* aNode)
|
||||
{
|
||||
DumpWithLevel(aNode->mChild, 0);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::DumpWithLevel(nsXFormsXPathNode* aNode, PRInt32 aLevel)
|
||||
{
|
||||
while (aNode) {
|
||||
if (aNode->mStartIndex < aNode->mEndIndex) {
|
||||
for (int i = 0; i < aLevel; i++) {
|
||||
printf(" ");
|
||||
}
|
||||
if (aNode->mCon) {
|
||||
printf("(+)");
|
||||
} else {
|
||||
printf("(|)");
|
||||
}
|
||||
OutputSubExpression(aNode->mStartIndex, aNode->mEndIndex);
|
||||
}
|
||||
DumpWithLevel(aNode->mChild, aLevel + 2);
|
||||
aNode = aNode->mSibling;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathParser::OutputSubExpression(PRInt32 aOffset, PRInt32 aEndOffset)
|
||||
{
|
||||
const nsDependentSubstring expr = Substring(mScanner.Expression(), aOffset, aEndOffset - aOffset);
|
||||
printf("%s\n", NS_ConvertUCS2toUTF8(expr).get());
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,112 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsXPathScanner.h"
|
||||
#include "nsXFormsXPathNode.h"
|
||||
|
||||
#define ANALYZE_STACK_SIZE 120
|
||||
|
||||
/**
|
||||
* The XPath Expression parser. Uses nsXFormsXPathScanner to scan the expression
|
||||
* and builds a parse tree of nsXFormsXPathNode's.
|
||||
*
|
||||
* @note Should be reimplemented and moved to Transformiix
|
||||
*
|
||||
*/
|
||||
class nsXFormsXPathParser {
|
||||
private:
|
||||
nsXFormsXPathScanner mScanner;
|
||||
nsXFormsXPathScanner::XPATHTOKEN mPeek;
|
||||
|
||||
PRBool mUsesDynamicFunc;
|
||||
|
||||
nsXFormsXPathNode* mHead;
|
||||
int mAnalyzeStackPointer;
|
||||
int mPredicateLevel;
|
||||
nsXFormsXPathNode* mStack[ANALYZE_STACK_SIZE];
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN PeekToken();
|
||||
nsXFormsXPathScanner::XPATHTOKEN PopToken();
|
||||
|
||||
void PushContext(PRInt32 aStartIndex = -100);
|
||||
void PushContext(nsXFormsXPathNode* mAnalyze);
|
||||
void EndContext();
|
||||
void RestartContext();
|
||||
nsXFormsXPathNode* JustContext();
|
||||
nsXFormsXPathNode* PopContext();
|
||||
|
||||
PRBool DoRelative();
|
||||
|
||||
void AbbreviatedStep();
|
||||
void AbsoluteLocationPath();
|
||||
void AdditiveExpression();
|
||||
void AndExpr();
|
||||
void AxisSpecifier();
|
||||
void EqualityExpr();
|
||||
void Expr();
|
||||
void FilterExpr();
|
||||
void FunctionCall();
|
||||
void LocationPath();
|
||||
void MultiplicationExpr();
|
||||
void NameTest();
|
||||
void NodeTest();
|
||||
void NodeType();
|
||||
void OrExpr();
|
||||
void PathExpr();
|
||||
void Predicate();
|
||||
PRBool PrimaryExpr();
|
||||
void RelationalExpression();
|
||||
void RelativeLocationPath();
|
||||
void Step();
|
||||
void UnaryExpr();
|
||||
void UnionExpr();
|
||||
|
||||
#ifdef DEBUG_XF_PARSER
|
||||
void Dump(nsXFormsXPathNode* aNode);
|
||||
void DumpWithLevel(nsXFormsXPathNode* aNode, PRInt32 aLevel);
|
||||
void OutputSubExpression(PRInt32 aOffset, PRInt32 aEndOffset);
|
||||
#endif
|
||||
|
||||
public:
|
||||
nsXFormsXPathParser();
|
||||
~nsXFormsXPathParser();
|
||||
|
||||
nsXFormsXPathNode* Parse(const nsAString& aExpression);
|
||||
PRBool UsesDynamicFunc() const;
|
||||
};
|
|
@ -0,0 +1,441 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsXPathScanner.h"
|
||||
#include "nsXFormsXPathXMLUtil.h"
|
||||
|
||||
MOZ_DECL_CTOR_COUNTER(nsXFormsXPathScanner)
|
||||
|
||||
nsXFormsXPathScanner::nsXFormsXPathScanner()
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsXPathScanner);
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::nsXFormsXPathScanner(const nsAString& aExpression)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsXFormsXPathScanner);
|
||||
|
||||
Init(aExpression);
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::~nsXFormsXPathScanner()
|
||||
{
|
||||
MOZ_COUNT_DTOR(nsXFormsXPathScanner);
|
||||
}
|
||||
|
||||
void
|
||||
nsXFormsXPathScanner::Init(const nsAString& aExpression)
|
||||
{
|
||||
mExpression = aExpression;
|
||||
mSize = mExpression.Length();
|
||||
mLength = 0;
|
||||
mOffset = -1;
|
||||
mLast = NONE;
|
||||
mState = NONE;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsXFormsXPathScanner::Length()
|
||||
{
|
||||
return mLength;
|
||||
}
|
||||
|
||||
PRInt32
|
||||
nsXFormsXPathScanner::Offset()
|
||||
{
|
||||
return mOffset;
|
||||
}
|
||||
|
||||
nsAString&
|
||||
nsXFormsXPathScanner::Expression()
|
||||
{
|
||||
return mExpression;
|
||||
}
|
||||
|
||||
PRUnichar
|
||||
nsXFormsXPathScanner::PopChar()
|
||||
{
|
||||
PRUnichar c = '\0';
|
||||
mLength++;
|
||||
if (mOffset + mLength < mSize) {
|
||||
c = mExpression[mOffset + mLength];
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
PRUnichar
|
||||
nsXFormsXPathScanner::PeekChar()
|
||||
{
|
||||
return PeekChar(mOffset + mLength + 1);
|
||||
}
|
||||
|
||||
PRUnichar
|
||||
nsXFormsXPathScanner::PeekChar(PRInt32 aOffset)
|
||||
{
|
||||
if (mSize > aOffset)
|
||||
return mExpression[aOffset];
|
||||
return '\0';
|
||||
}
|
||||
|
||||
PRUnichar
|
||||
nsXFormsXPathScanner::NextNonWhite()
|
||||
{
|
||||
return PeekChar(GetOffsetForNonWhite());
|
||||
}
|
||||
|
||||
int
|
||||
nsXFormsXPathScanner::GetOffsetForNonWhite()
|
||||
{
|
||||
PRInt32 co = mOffset + mLength + 1;
|
||||
while (nsXFormsXPathXMLUtil::IsWhitespace(PeekChar(co)))
|
||||
co++;
|
||||
return co;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathScanner::HasMoreTokens()
|
||||
{
|
||||
return mState != XPATHEOF;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::NextToken()
|
||||
{
|
||||
if (mState != WHITESPACE)
|
||||
mLast = mState;
|
||||
mOffset = mOffset + mLength;
|
||||
mLength = 0;
|
||||
|
||||
PRUnichar c = PeekChar();
|
||||
if (c == '\0') {
|
||||
mState = XPATHEOF;
|
||||
} else if (nsXFormsXPathXMLUtil::IsDigit(c)) {
|
||||
mState = ScanNumber();
|
||||
} else if (c == '_' || nsXFormsXPathXMLUtil::IsLetter(c)) {
|
||||
mState = ScanQName();
|
||||
} else if (c == '"' || c == '\'') {
|
||||
mState = ScanLiteral();
|
||||
} else {
|
||||
switch (c) {
|
||||
case '(':
|
||||
mState = LPARAN;
|
||||
PopChar();
|
||||
break;
|
||||
|
||||
case ')':
|
||||
mState = RPARAN;
|
||||
PopChar();
|
||||
break;
|
||||
|
||||
case '[':
|
||||
mState = LBRACK;
|
||||
PopChar();
|
||||
break;
|
||||
|
||||
case ']':
|
||||
mState = RBRACK;
|
||||
PopChar();
|
||||
break;
|
||||
|
||||
case '@':
|
||||
mState = AT;
|
||||
PopChar();
|
||||
break;
|
||||
|
||||
case ',':
|
||||
mState = COMMA;
|
||||
PopChar();
|
||||
break;
|
||||
|
||||
case ':':
|
||||
PopChar();
|
||||
if (PeekChar() == ':') {
|
||||
mState = COLONCOLON;
|
||||
PopChar();
|
||||
} else
|
||||
mState = ERRORXPATHTOKEN;
|
||||
break;
|
||||
|
||||
case '.':
|
||||
PopChar();
|
||||
if (PeekChar() == '.') {
|
||||
mState = DOTDOT;
|
||||
PopChar();
|
||||
} else if (nsXFormsXPathXMLUtil::IsDigit(PeekChar()))
|
||||
mState = ScanNumber();
|
||||
else
|
||||
mState = DOT;
|
||||
break;
|
||||
|
||||
case '$':
|
||||
mState = ScanVariable();
|
||||
break;
|
||||
|
||||
case '/':
|
||||
PopChar();
|
||||
if (PeekChar() == '/') {
|
||||
mState = SLASHSLASH;
|
||||
PopChar();
|
||||
} else
|
||||
mState = SLASH;
|
||||
break;
|
||||
|
||||
case '|':
|
||||
PopChar();
|
||||
mState = UNION;
|
||||
break;
|
||||
|
||||
case '+':
|
||||
PopChar();
|
||||
mState = PLUS;
|
||||
break;
|
||||
|
||||
case '-':
|
||||
PopChar();
|
||||
mState = MINUS;
|
||||
break;
|
||||
|
||||
case '=':
|
||||
PopChar();
|
||||
mState = EQUAL;
|
||||
break;
|
||||
|
||||
case '!':
|
||||
PopChar();
|
||||
if (PeekChar() == '=') {
|
||||
mState = NOTEQUAL;
|
||||
PopChar();
|
||||
} else
|
||||
mState = ERRORXPATHTOKEN;
|
||||
break;
|
||||
|
||||
case '<':
|
||||
PopChar();
|
||||
if (PeekChar() == '=') {
|
||||
mState = LEQUAL;
|
||||
PopChar();
|
||||
} else
|
||||
mState = LESS;
|
||||
break;
|
||||
|
||||
case '>':
|
||||
PopChar();
|
||||
if (PeekChar() == '=') {
|
||||
mState = GEQUAL;
|
||||
PopChar();
|
||||
} else
|
||||
mState = GREATER;
|
||||
break;
|
||||
|
||||
case '*':
|
||||
PopChar();
|
||||
mState = SolveStar();
|
||||
break;
|
||||
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\t':
|
||||
case ' ':
|
||||
mState = ScanWhitespace();
|
||||
break;
|
||||
|
||||
default:
|
||||
PopChar();
|
||||
mState = ERRORXPATHTOKEN;
|
||||
}
|
||||
}
|
||||
|
||||
return mState;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathScanner::SolveDiambiguate()
|
||||
{
|
||||
return mLast != NONE && (mLast != AT && mLast != COLONCOLON && mLast != LPARAN && mLast != LBRACK &&
|
||||
mLast != AND && mLast != OR && mLast != DIV && mLast != MOD && mLast != SLASH && mLast != MULTIPLYOPERATOR &&
|
||||
mLast != SLASHSLASH && mLast != UNION && mLast != PLUS && mLast != MINUS && mLast != NOTEQUAL && mLast != EQUAL && mLast != LESS &&
|
||||
mLast != LEQUAL && mLast != GEQUAL && mLast != GREATER && mLast != COMMA);
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::SolveStar()
|
||||
{
|
||||
if (SolveDiambiguate())
|
||||
return MULTIPLYOPERATOR;
|
||||
return STAR;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::ScanNumber()
|
||||
{
|
||||
PRUnichar c = PopChar();
|
||||
PRBool decimal = (c == '.');
|
||||
|
||||
while (c != '\0') {
|
||||
c = PeekChar();
|
||||
if (!decimal && c == '.') {
|
||||
decimal = PR_TRUE;
|
||||
} else if (!nsXFormsXPathXMLUtil::IsDigit(c)) {
|
||||
return NUMBER;
|
||||
}
|
||||
PopChar();
|
||||
}
|
||||
return NUMBER;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::ScanVariable()
|
||||
{
|
||||
PopChar();
|
||||
if (ScanQName() != ERRORXPATHTOKEN)
|
||||
return VARIABLE;
|
||||
return ERRORXPATHTOKEN;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::ScanWhitespace()
|
||||
{
|
||||
PRUnichar c;
|
||||
do {
|
||||
PopChar();
|
||||
c = PeekChar();
|
||||
} while (nsXFormsXPathXMLUtil::IsWhitespace(c));
|
||||
|
||||
return WHITESPACE;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::ScanLiteral()
|
||||
{
|
||||
PRUnichar c = PopChar();
|
||||
PRUnichar p;
|
||||
while ((p = PeekChar()) != c && p != '\0')
|
||||
PopChar();
|
||||
if (p == '\0')
|
||||
return ERRORXPATHTOKEN;
|
||||
PopChar();
|
||||
return LITERAL;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::ScanQName()
|
||||
{
|
||||
XPATHTOKEN second = NONE;
|
||||
ScanNCName();
|
||||
if (PeekChar() == ':' && PeekChar(mOffset + mLength + 2) != ':') {
|
||||
PopChar();
|
||||
second = ScanNCName();
|
||||
}
|
||||
|
||||
// TODO: nsSubString and .Equals() ?
|
||||
nsDependentSubstring image = Substring(mExpression, Offset());
|
||||
|
||||
if (SolveDiambiguate()) {
|
||||
if (image.EqualsASCII("and", 3))
|
||||
return AND;
|
||||
else if (image.EqualsASCII("or", 2))
|
||||
return OR;
|
||||
else if (image.EqualsASCII("mod", 3))
|
||||
return MOD;
|
||||
else if (image.EqualsASCII("div", 3))
|
||||
return DIV;
|
||||
return ERRORXPATHTOKEN;
|
||||
}
|
||||
|
||||
PRUnichar c = NextNonWhite();
|
||||
if (c == '(') {
|
||||
if (image.EqualsASCII("comment", 7))
|
||||
return COMMENT;
|
||||
else if (image.EqualsASCII("text", 4))
|
||||
return TEXT;
|
||||
else if (image.EqualsASCII("processing-instruction", 22))
|
||||
return PI;
|
||||
else if (image.EqualsASCII("node", 4))
|
||||
return NODE;
|
||||
|
||||
return FUNCTIONNAME;
|
||||
}
|
||||
|
||||
PRInt32 of = GetOffsetForNonWhite();
|
||||
if (PeekChar(of) == ':' && PeekChar(of + 1) == ':') {
|
||||
if (image.EqualsASCII("ancestor", 8))
|
||||
return ANCESTOR;
|
||||
else if (image.EqualsASCII("ancestor-or-self", 16))
|
||||
return ANCESTOR_OR_SELF;
|
||||
else if (image.EqualsASCII("attribute", 9))
|
||||
return ATTRIBUTE;
|
||||
else if (image.EqualsASCII("child", 5))
|
||||
return CHILD;
|
||||
else if (image.EqualsASCII("descendant", 10))
|
||||
return DESCENDANT;
|
||||
else if (image.EqualsASCII("descendant-or-self", 18))
|
||||
return DESCENDANT_OR_SELF;
|
||||
else if (image.EqualsASCII("following", 9))
|
||||
return FOLLOWING;
|
||||
else if (image.EqualsASCII("following-sibling", 17))
|
||||
return FOLLOWING_SIBLING;
|
||||
else if (image.EqualsASCII("namespace", 9))
|
||||
return NAMESPACE;
|
||||
else if (image.EqualsASCII("parent", 6))
|
||||
return PARENT;
|
||||
else if (image.EqualsASCII("preceding", 9))
|
||||
return PRECEDING;
|
||||
else if (image.EqualsASCII("preceding-sibling", 17))
|
||||
return PRECEDING_SIBLING;
|
||||
else if (image.EqualsASCII("self", 4))
|
||||
return SELF;
|
||||
return ERRORXPATHTOKEN;
|
||||
}
|
||||
return second != NONE ? QNAME : NCNAME;
|
||||
}
|
||||
|
||||
nsXFormsXPathScanner::XPATHTOKEN
|
||||
nsXFormsXPathScanner::ScanNCName()
|
||||
{
|
||||
PRUnichar c = PopChar();
|
||||
if (c != '_' && !nsXFormsXPathXMLUtil::IsLetter(c)) {
|
||||
return ERRORXPATHTOKEN;
|
||||
}
|
||||
|
||||
while (nsXFormsXPathXMLUtil::IsNCNameChar(PeekChar())) {
|
||||
PopChar();
|
||||
}
|
||||
|
||||
return NCNAME;
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#ifndef __NSXFORMSXPATHSCANNER_H__
|
||||
#define __NSXFORMSXPATHSCANNER_H__
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
/**
|
||||
* The XPath Expression scanner, used by nsXFormsXPathParser.
|
||||
*
|
||||
* @note Should be reimplemented and moved to Transformiix
|
||||
*
|
||||
*/
|
||||
class nsXFormsXPathScanner
|
||||
{
|
||||
public:
|
||||
enum XPATHTOKEN {
|
||||
LPARAN, RPARAN, LBRACK, RBRACK, AT, COMMA,
|
||||
COLONCOLON, DOT, DOTDOT, SLASH, SLASHSLASH, UNION,
|
||||
PLUS, MINUS, EQUAL, NOTEQUAL, LEQUAL, LESS, GEQUAL,
|
||||
GREATER, MULTIPLYOPERATOR, WHITESPACE, NUMBER,
|
||||
LITERAL, AND, OR, MOD, DIV, NODE, PI, TEXT, COMMENT,
|
||||
FUNCTIONNAME, NCNAME, QNAME, VARIABLE, STAR, ANCESTOR,
|
||||
ANCESTOR_OR_SELF, ATTRIBUTE, CHILD, DESCENDANT,
|
||||
DESCENDANT_OR_SELF, FOLLOWING, FOLLOWING_SIBLING, NAMESPACE,
|
||||
PARENT, PRECEDING, PRECEDING_SIBLING, SELF, XPATHEOF, ERRORXPATHTOKEN, NONE
|
||||
};
|
||||
|
||||
private:
|
||||
XPATHTOKEN mState, mLast;
|
||||
nsAutoString mExpression;
|
||||
PRInt32 mOffset, mLength, mSize;
|
||||
|
||||
PRUnichar PopChar();
|
||||
PRUnichar PeekChar();
|
||||
PRUnichar PeekChar(PRInt32 offset);
|
||||
PRUnichar NextNonWhite();
|
||||
PRInt32 GetOffsetForNonWhite();
|
||||
|
||||
PRBool SolveDiambiguate();
|
||||
XPATHTOKEN SolveStar();
|
||||
XPATHTOKEN ScanNumber();
|
||||
XPATHTOKEN ScanVariable();
|
||||
XPATHTOKEN ScanWhitespace();
|
||||
XPATHTOKEN ScanLiteral();
|
||||
XPATHTOKEN ScanQName();
|
||||
XPATHTOKEN ScanNCName();
|
||||
|
||||
|
||||
public:
|
||||
nsXFormsXPathScanner();
|
||||
nsXFormsXPathScanner(const nsAString& aExpression);
|
||||
~nsXFormsXPathScanner();
|
||||
|
||||
void Init(const nsAString& aExpression);
|
||||
XPATHTOKEN NextToken();
|
||||
PRInt32 Offset();
|
||||
PRInt32 Length();
|
||||
void Image(PRInt32& aOffset, PRInt32& aLength);
|
||||
PRBool HasMoreTokens();
|
||||
nsAString& Expression();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,137 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsXFormsXPathXMLUtil.h"
|
||||
|
||||
static const PRUint32 BASECHAR_RANGE_LENGTH = 404;
|
||||
static const PRUnichar BASECHAR_RANGE[] = {
|
||||
L'\x0041',L'\x005a',L'\x0061',L'\x007a',L'\x00c0',L'\x00d6',L'\x00d8',L'\x00f6',L'\x00f8',L'\x00ff',L'\x0100',L'\x0131',L'\x0134',L'\x013e',L'\x0141',L'\x0148',L'\x014a',L'\x017e',L'\x0180',L'\x01c3',L'\x01cd',L'\x01f0',L'\x01f4',L'\x01f5',L'\x01fa',L'\x0217',L'\x0250',L'\x02a8',L'\x02bb',L'\x02c1',L'\x0386',L'\x0386',L'\x0388',L'\x038a',L'\x038c',L'\x038c',L'\x038e',L'\x03a1',L'\x03a3',L'\x03ce'
|
||||
,L'\x03d0',L'\x03d6',L'\x03da',L'\x03da',L'\x03dc',L'\x03dc',L'\x03de',L'\x03de',L'\x03e0',L'\x03e0',L'\x03e2',L'\x03f3',L'\x0401',L'\x040c',L'\x040e',L'\x044f',L'\x0451',L'\x045c',L'\x045e',L'\x0481',L'\x0490',L'\x04c4',L'\x04c7',L'\x04c8',L'\x04cb',L'\x04cc',L'\x04d0',L'\x04eb',L'\x04ee',L'\x04f5',L'\x04f8',L'\x04f9',L'\x0531',L'\x0556',L'\x0559',L'\x0559',L'\x0561',L'\x0586',L'\x05d0',L'\x05ea'
|
||||
,L'\x05f0',L'\x05f2',L'\x0621',L'\x063a',L'\x0641',L'\x064a',L'\x0671',L'\x06b7',L'\x06ba',L'\x06be',L'\x06c0',L'\x06ce',L'\x06d0',L'\x06d3',L'\x06d5',L'\x06d5',L'\x06e5',L'\x06e6',L'\x0905',L'\x0939',L'\x093d',L'\x093d',L'\x0958',L'\x0961',L'\x0985',L'\x098c',L'\x098f',L'\x0990',L'\x0993',L'\x09a8',L'\x09aa',L'\x09b0',L'\x09b2',L'\x09b2',L'\x09b6',L'\x09b9',L'\x09dc',L'\x09dd',L'\x09df',L'\x09e1'
|
||||
,L'\x09f0',L'\x09f1',L'\x0a05',L'\x0a0a',L'\x0a0f',L'\x0a10',L'\x0a13',L'\x0a28',L'\x0a2a',L'\x0a30',L'\x0a32',L'\x0a33',L'\x0a35',L'\x0a36',L'\x0a38',L'\x0a39',L'\x0a59',L'\x0a5c',L'\x0a5e',L'\x0a5e',L'\x0a72',L'\x0a74',L'\x0a85',L'\x0a8b',L'\x0a8d',L'\x0a8d',L'\x0a8f',L'\x0a91',L'\x0a93',L'\x0aa8',L'\x0aaa',L'\x0ab0',L'\x0ab2',L'\x0ab3',L'\x0ab5',L'\x0ab9',L'\x0abd',L'\x0abd',L'\x0ae0',L'\x0ae0'
|
||||
,L'\x0b05',L'\x0b0c',L'\x0b0f',L'\x0b10',L'\x0b13',L'\x0b28',L'\x0b2a',L'\x0b30',L'\x0b32',L'\x0b33',L'\x0b36',L'\x0b39',L'\x0b3d',L'\x0b3d',L'\x0b5c',L'\x0b5d',L'\x0b5f',L'\x0b61',L'\x0b85',L'\x0b8a',L'\x0b8e',L'\x0b90',L'\x0b92',L'\x0b95',L'\x0b99',L'\x0b9a',L'\x0b9c',L'\x0b9c',L'\x0b9e',L'\x0b9f',L'\x0ba3',L'\x0ba4',L'\x0ba8',L'\x0baa',L'\x0bae',L'\x0bb5',L'\x0bb7',L'\x0bb9',L'\x0c05',L'\x0c0c'
|
||||
,L'\x0c0e',L'\x0c10',L'\x0c12',L'\x0c28',L'\x0c2a',L'\x0c33',L'\x0c35',L'\x0c39',L'\x0c60',L'\x0c61',L'\x0c85',L'\x0c8c',L'\x0c8e',L'\x0c90',L'\x0c92',L'\x0ca8',L'\x0caa',L'\x0cb3',L'\x0cb5',L'\x0cb9',L'\x0cde',L'\x0cde',L'\x0ce0',L'\x0ce1',L'\x0d05',L'\x0d0c',L'\x0d0e',L'\x0d10',L'\x0d12',L'\x0d28',L'\x0d2a',L'\x0d39',L'\x0d60',L'\x0d61',L'\x0e01',L'\x0e2e',L'\x0e30',L'\x0e30',L'\x0e32',L'\x0e33'
|
||||
,L'\x0e40',L'\x0e45',L'\x0e81',L'\x0e82',L'\x0e84',L'\x0e84',L'\x0e87',L'\x0e88',L'\x0e8a',L'\x0e8a',L'\x0e8d',L'\x0e8d',L'\x0e94',L'\x0e97',L'\x0e99',L'\x0e9f',L'\x0ea1',L'\x0ea3',L'\x0ea5',L'\x0ea5',L'\x0ea7',L'\x0ea7',L'\x0eaa',L'\x0eab',L'\x0ead',L'\x0eae',L'\x0eb0',L'\x0eb0',L'\x0eb2',L'\x0eb3',L'\x0ebd',L'\x0ebd',L'\x0ec0',L'\x0ec4',L'\x0f40',L'\x0f47',L'\x0f49',L'\x0f69',L'\x10a0',L'\x10c5'
|
||||
,L'\x10d0',L'\x10f6',L'\x1100',L'\x1100',L'\x1102',L'\x1103',L'\x1105',L'\x1107',L'\x1109',L'\x1109',L'\x110b',L'\x110c',L'\x110e',L'\x1112',L'\x113c',L'\x113c',L'\x113e',L'\x113e',L'\x1140',L'\x1140',L'\x114c',L'\x114c',L'\x114e',L'\x114e',L'\x1150',L'\x1150',L'\x1154',L'\x1155',L'\x1159',L'\x1159',L'\x115f',L'\x1161',L'\x1163',L'\x1163',L'\x1165',L'\x1165',L'\x1167',L'\x1167',L'\x1169',L'\x1169'
|
||||
,L'\x116d',L'\x116e',L'\x1172',L'\x1173',L'\x1175',L'\x1175',L'\x119e',L'\x119e',L'\x11a8',L'\x11a8',L'\x11ab',L'\x11ab',L'\x11ae',L'\x11af',L'\x11b7',L'\x11b8',L'\x11ba',L'\x11ba',L'\x11bc',L'\x11c2',L'\x11eb',L'\x11eb',L'\x11f0',L'\x11f0',L'\x11f9',L'\x11f9',L'\x1e00',L'\x1e9b',L'\x1ea0',L'\x1ef9',L'\x1f00',L'\x1f15',L'\x1f18',L'\x1f1d',L'\x1f20',L'\x1f45',L'\x1f48',L'\x1f4d',L'\x1f50',L'\x1f57'
|
||||
,L'\x1f59',L'\x1f59',L'\x1f5b',L'\x1f5b',L'\x1f5d',L'\x1f5d',L'\x1f5f',L'\x1f7d',L'\x1f80',L'\x1fb4',L'\x1fb6',L'\x1fbc',L'\x1fbe',L'\x1fbe',L'\x1fc2',L'\x1fc4',L'\x1fc6',L'\x1fcc',L'\x1fd0',L'\x1fd3',L'\x1fd6',L'\x1fdb',L'\x1fe0',L'\x1fec',L'\x1ff2',L'\x1ff4',L'\x1ff6',L'\x1ffc',L'\x2126',L'\x2126',L'\x212a',L'\x212b',L'\x212e',L'\x212e',L'\x2180',L'\x2182',L'\x3041',L'\x3094',L'\x30a1',L'\x30fa'
|
||||
,L'\x3105',L'\x312c',L'\xac00',L'\xd7a3'};
|
||||
|
||||
static const PRUint32 IDEOGRAPHIC_RANGE_LENGTH = 6;
|
||||
static const PRUnichar IDEOGRAPHIC_RANGE[] = {
|
||||
L'\x4e00',L'\x9fa5',L'\x3007',L'\x3007',L'\x3021',L'\x3029'
|
||||
};
|
||||
|
||||
static const PRUint32 COMBINING_CHAR_RANGE_LENGTH = 190;
|
||||
static const PRUnichar COMBINING_CHAR_RANGE[] = {
|
||||
L'\x0300',L'\x0345',L'\x0360',L'\x0361',L'\x0483',L'\x0486',L'\x0591',L'\x05a1',L'\x05a3',L'\x05b9',L'\x05bb',L'\x05bd',L'\x05bf',L'\x05bf',L'\x05c1',L'\x05c2',L'\x05c4',L'\x05c4',L'\x064b',L'\x0652',L'\x0670',L'\x0670',L'\x06d6',L'\x06dc',L'\x06dd',L'\x06df',L'\x06e0',L'\x06e4',L'\x06e7',L'\x06e8',L'\x06ea',L'\x06ed',L'\x0901',L'\x0903',L'\x093c',L'\x093c',L'\x093e',L'\x094c',L'\x094d',L'\x094d'
|
||||
,L'\x0951',L'\x0954',L'\x0962',L'\x0963',L'\x0981',L'\x0983',L'\x09bc',L'\x09bc',L'\x09be',L'\x09be',L'\x09bf',L'\x09bf',L'\x09c0',L'\x09c4',L'\x09c7',L'\x09c8',L'\x09cb',L'\x09cd',L'\x09d7',L'\x09d7',L'\x09e2',L'\x09e3',L'\x0a02',L'\x0a02',L'\x0a3c',L'\x0a3c',L'\x0a3e',L'\x0a3e',L'\x0a3f',L'\x0a3f',L'\x0a40',L'\x0a42',L'\x0a47',L'\x0a48',L'\x0a4b',L'\x0a4d',L'\x0a70',L'\x0a71',L'\x0a81',L'\x0a83'
|
||||
,L'\x0abc',L'\x0abc',L'\x0abe',L'\x0ac5',L'\x0ac7',L'\x0ac9',L'\x0acb',L'\x0acd',L'\x0b01',L'\x0b03',L'\x0b3c',L'\x0b3c',L'\x0b3e',L'\x0b43',L'\x0b47',L'\x0b48',L'\x0b4b',L'\x0b4d',L'\x0b56',L'\x0b57',L'\x0b82',L'\x0b83',L'\x0bbe',L'\x0bc2',L'\x0bc6',L'\x0bc8',L'\x0bca',L'\x0bcd',L'\x0bd7',L'\x0bd7',L'\x0c01',L'\x0c03',L'\x0c3e',L'\x0c44',L'\x0c46',L'\x0c48',L'\x0c4a',L'\x0c4d',L'\x0c55',L'\x0c56'
|
||||
,L'\x0c82',L'\x0c83',L'\x0cbe',L'\x0cc4',L'\x0cc6',L'\x0cc8',L'\x0cca',L'\x0ccd',L'\x0cd5',L'\x0cd6',L'\x0d02',L'\x0d03',L'\x0d3e',L'\x0d43',L'\x0d46',L'\x0d48',L'\x0d4a',L'\x0d4d',L'\x0d57',L'\x0d57',L'\x0e31',L'\x0e31',L'\x0e34',L'\x0e3a',L'\x0e47',L'\x0e4e',L'\x0eb1',L'\x0eb1',L'\x0eb4',L'\x0eb9',L'\x0ebb',L'\x0ebc',L'\x0ec8',L'\x0ecd',L'\x0f18',L'\x0f19',L'\x0f35',L'\x0f35',L'\x0f37',L'\x0f37'
|
||||
,L'\x0f39',L'\x0f39',L'\x0f3e',L'\x0f3e',L'\x0f3f',L'\x0f3f',L'\x0f71',L'\x0f84',L'\x0f86',L'\x0f8b',L'\x0f90',L'\x0f95',L'\x0f97',L'\x0f97',L'\x0f99',L'\x0fad',L'\x0fb1',L'\x0fb7',L'\x0fb9',L'\x0fb9',L'\x20d0',L'\x20dc',L'\x20e1',L'\x20e1',L'\x302a',L'\x302f',L'\x3099',L'\x3099',L'\x309a',L'\x309a'
|
||||
};
|
||||
|
||||
static const PRUint32 DIGIT_RANGE_LENGTH = 30;
|
||||
static const PRUnichar DIGIT_RANGE[] = {
|
||||
L'\x0030',L'\x0039',L'\x0660',L'\x0669',L'\x06f0',L'\x06f9',L'\x0966',L'\x096f',L'\x09e6',L'\x09ef',L'\x0a66',L'\x0a6f',L'\x0ae6',L'\x0aef',L'\x0b66',L'\x0b6f',L'\x0be7',L'\x0bef',L'\x0c66',L'\x0c6f',L'\x0ce6',L'\x0cef',L'\x0d66',L'\x0d6f',L'\x0e50',L'\x0e59',L'\x0ed0',L'\x0ed9',L'\x0f20',L'\x0f29'
|
||||
};
|
||||
|
||||
static const PRUint32 EXTENDER_RANGE_LENGTH = 22;
|
||||
static const PRUnichar EXTENDER_RANGE[] = {
|
||||
L'\x00b7',L'\x00b7',L'\x02d0',L'\x02d0',L'\x02d1',L'\x02d1',L'\x0387',L'\x0387',L'\x0640',L'\x0640',L'\x0e46',L'\x0e46',L'\x0ec6',L'\x0ec6',L'\x3005',L'\x3005',L'\x3031',L'\x3035',L'\x309d',L'\x309e',L'\x30fc',L'\x30fe'
|
||||
};
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsInRange(const PRUnichar* range, const PRUint32 range_length, const PRUnichar c)
|
||||
{
|
||||
PRBool inrange = false;
|
||||
for (PRUint32 i = 0; !inrange && c >= range[i] && i < range_length; i += 2) {
|
||||
inrange = c >= range[i] && c <= range[i + 1];
|
||||
}
|
||||
return inrange;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsWhitespace(const PRUnichar c)
|
||||
{
|
||||
return (c == L'\r' || c == L' ' || c == L'\n' || c == L'\t');
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsDigit(const PRUnichar c)
|
||||
{
|
||||
return IsInRange(DIGIT_RANGE, DIGIT_RANGE_LENGTH, c);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsIdeographic(const PRUnichar c)
|
||||
{
|
||||
return IsInRange(IDEOGRAPHIC_RANGE, IDEOGRAPHIC_RANGE_LENGTH, c);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsLetter(const PRUnichar c)
|
||||
{
|
||||
return IsBaseChar(c) || IsIdeographic(c);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsBaseChar(const PRUnichar c)
|
||||
{
|
||||
return IsInRange(BASECHAR_RANGE, BASECHAR_RANGE_LENGTH, c);
|
||||
}
|
||||
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsNCNameChar(const PRUnichar c)
|
||||
{
|
||||
return IsLetter(c) || IsDigit(c) || c == L'.' || c == L'-' || c == L'_' || IsCombiningChar(c) || IsExtender(c);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsCombiningChar(const PRUnichar c)
|
||||
{
|
||||
return IsInRange(COMBINING_CHAR_RANGE, COMBINING_CHAR_RANGE_LENGTH, c);
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsXFormsXPathXMLUtil::IsExtender(const PRUnichar c)
|
||||
{
|
||||
return IsInRange(EXTENDER_RANGE, EXTENDER_RANGE_LENGTH, c);
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla 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/MPL/
|
||||
*
|
||||
* 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 XForms support.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Novell, Inc.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2004
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Allan Beaufour <abeaufour@novell.com>
|
||||
* David Landwehr <dlandwehr@novell.com>
|
||||
*
|
||||
* 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 MPL, 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 MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include "nsString.h"
|
||||
|
||||
/**
|
||||
* Misc. utility functions for determining the class of a character, used by
|
||||
* nsXFormsXPathScanner.
|
||||
*
|
||||
* @note Should be reimplemented and moved to Transformiix
|
||||
*
|
||||
*/
|
||||
class nsXFormsXPathXMLUtil {
|
||||
private:
|
||||
/** Helper function for public functions */
|
||||
static PRBool IsInRange(const PRUnichar* range, const PRUint32 range_length, const PRUnichar c);
|
||||
|
||||
public:
|
||||
/** Checks if a char is a whitespace */
|
||||
static PRBool IsWhitespace(const PRUnichar c);
|
||||
|
||||
/** Checks of a char is a digit */
|
||||
static PRBool IsDigit(const PRUnichar c);
|
||||
|
||||
/** Checks if a char is an ideographic */
|
||||
static PRBool IsIdeographic(const PRUnichar c);
|
||||
|
||||
/** Checks if a char is a letter */
|
||||
static PRBool IsLetter(const PRUnichar c);
|
||||
|
||||
/** Checks if a char is a base char */
|
||||
static PRBool IsBaseChar(const PRUnichar c);
|
||||
|
||||
/** Check is a char matches the first rule of a NCName */
|
||||
static PRBool IsNCNameChar(const PRUnichar c);
|
||||
|
||||
/** Check if a char is a combining char */
|
||||
static PRBool IsCombiningChar(const PRUnichar c);
|
||||
|
||||
/** Check if a char is an extender */
|
||||
static PRBool IsExtender(const PRUnichar c);
|
||||
};
|
Загрузка…
Ссылка в новой задаче