diff options
author | Steve Block <steveblock@google.com> | 2011-05-06 11:45:16 +0100 |
---|---|---|
committer | Steve Block <steveblock@google.com> | 2011-05-12 13:44:10 +0100 |
commit | cad810f21b803229eb11403f9209855525a25d57 (patch) | |
tree | 29a6fd0279be608e0fe9ffe9841f722f0f4e4269 /Source/WebCore/wml | |
parent | 121b0cf4517156d0ac5111caf9830c51b69bae8f (diff) | |
download | external_webkit-cad810f21b803229eb11403f9209855525a25d57.zip external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.gz external_webkit-cad810f21b803229eb11403f9209855525a25d57.tar.bz2 |
Merge WebKit at r75315: Initial merge by git.
Change-Id: I570314b346ce101c935ed22a626b48c2af266b84
Diffstat (limited to 'Source/WebCore/wml')
74 files changed, 7674 insertions, 0 deletions
diff --git a/Source/WebCore/wml/WMLAElement.cpp b/Source/WebCore/wml/WMLAElement.cpp new file mode 100644 index 0000000..00067fe --- /dev/null +++ b/Source/WebCore/wml/WMLAElement.cpp @@ -0,0 +1,158 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Simon Hausmann <hausmann@kde.org> + * Copyright (C) 2003, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved. + * (C) 2006 Graham Dennis (graham.dennis@gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLAElement.h" + +#include "Attribute.h" +#include "Event.h" +#include "EventHandler.h" +#include "EventNames.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "HTMLAnchorElement.h" +#include "HTMLNames.h" +#include "HTMLParserIdioms.h" +#include "KeyboardEvent.h" +#include "MouseEvent.h" +#include "RenderBox.h" +#include "ResourceHandle.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLAElement::WMLAElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLAElement> WMLAElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLAElement(tagName, document)); +} + +void WMLAElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::hrefAttr) { + bool wasLink = isLink(); + setIsLink(!attr->isNull()); + if (wasLink != isLink()) + setNeedsStyleRecalc(); + if (isLink() && document()->isDNSPrefetchEnabled()) { + String value = attr->value(); + if (protocolIs(value, "http") || protocolIs(value, "https") || value.startsWith("//")) + ResourceHandle::prepareForURL(document()->completeURL(value)); + } + } else if (attr->name() == HTMLNames::nameAttr + || attr->name() == HTMLNames::titleAttr + || attr->name() == HTMLNames::relAttr) { + // Do nothing. + } else + WMLElement::parseMappedAttribute(attr); +} + +bool WMLAElement::supportsFocus() const +{ + return isLink() || WMLElement::supportsFocus(); +} + +bool WMLAElement::isMouseFocusable() const +{ + return false; +} + +bool WMLAElement::isKeyboardFocusable(KeyboardEvent* event) const +{ + if (!isFocusable()) + return false; + + if (!document()->frame()) + return false; + + if (!document()->frame()->eventHandler()->tabsToLinks(event)) + return false; + + if (!renderer() || !renderer()->isBoxModelObject()) + return false; + + // Before calling absoluteRects, check for the common case where the renderer + // is non-empty, since this is a faster check and almost always returns true. + RenderBoxModelObject* box = toRenderBoxModelObject(renderer()); + if (!box->borderBoundingBox().isEmpty()) + return true; + + Vector<IntRect> rects; + FloatPoint absPos = renderer()->localToAbsolute(); + renderer()->absoluteRects(rects, absPos.x(), absPos.y()); + size_t n = rects.size(); + for (size_t i = 0; i < n; ++i) + if (!rects[i].isEmpty()) + return true; + + return false; +} + +void WMLAElement::defaultEventHandler(Event* event) +{ + if (isLink()) { + if (focused() && isEnterKeyKeydownEvent(event)) { + event->setDefaultHandled(); + dispatchSimulatedClick(event); + return; + } + + if (isLinkClick(event)) { + handleLinkClick(event, document(), stripLeadingAndTrailingHTMLSpaces(getAttribute(HTMLNames::hrefAttr)), target(), event); + return; + } + } + + WMLElement::defaultEventHandler(event); +} + +void WMLAElement::accessKeyAction(bool sendToAnyElement) +{ + // send the mouse button events if the caller specified sendToAnyElement + dispatchSimulatedClick(0, sendToAnyElement); +} + +bool WMLAElement::isURLAttribute(Attribute *attr) const +{ + return attr->name() == HTMLNames::hrefAttr; +} + +String WMLAElement::target() const +{ + return getAttribute(HTMLNames::targetAttr); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLAElement.h b/Source/WebCore/wml/WMLAElement.h new file mode 100644 index 0000000..9dcda6b --- /dev/null +++ b/Source/WebCore/wml/WMLAElement.h @@ -0,0 +1,56 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Simon Hausmann <hausmann@kde.org> + * Copyright (C) 2007, 2008 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLAElement_h +#define WMLAElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLAElement : public WMLElement { +public: + static PassRefPtr<WMLAElement> create(const QualifiedName& tagName, Document*); + + WMLAElement(const QualifiedName& tagName, Document*); + + virtual bool supportsFocus() const; + virtual bool isMouseFocusable() const; + virtual bool isKeyboardFocusable(KeyboardEvent*) const; + + virtual void parseMappedAttribute(Attribute*); + virtual void defaultEventHandler(Event*); + + virtual void accessKeyAction(bool fullAction); + virtual bool isURLAttribute(Attribute*) const; + + virtual String target() const; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLAccessElement.cpp b/Source/WebCore/wml/WMLAccessElement.cpp new file mode 100644 index 0000000..0e13106 --- /dev/null +++ b/Source/WebCore/wml/WMLAccessElement.cpp @@ -0,0 +1,77 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLAccessElement.h" + +#include "Attribute.h" +#include "WMLDocument.h" +#include "WMLNames.h" +#include "WMLVariables.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLAccessElement::WMLAccessElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLAccessElement> WMLAccessElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLAccessElement(tagName, document)); +} + +void WMLAccessElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == domainAttr) { + String value = parseValueForbiddingVariableReferences(attr->value()); + if (value.isEmpty()) + return; + + m_domain = value; + } else if (attr->name() == pathAttr) { + String value = parseValueForbiddingVariableReferences(attr->value()); + if (value.isEmpty()) + return; + + m_path = value; + } else + WMLElement::parseMappedAttribute(attr); +} + +void WMLAccessElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + WMLPageState* pageState = wmlPageStateForDocument(document()); + if (!pageState || pageState->processAccessControlData(m_domain, m_path)) + return; + + pageState->resetAccessControlData(); + reportWMLError(document(), WMLErrorMultipleAccessElements); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLAccessElement.h b/Source/WebCore/wml/WMLAccessElement.h new file mode 100644 index 0000000..eb7436c --- /dev/null +++ b/Source/WebCore/wml/WMLAccessElement.h @@ -0,0 +1,46 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLAccessElement_h +#define WMLAccessElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLAccessElement : public WMLElement { +public: + static PassRefPtr<WMLAccessElement> create(const QualifiedName& tagName, Document*); + + WMLAccessElement(const QualifiedName& tagName, Document*); + + virtual void parseMappedAttribute(Attribute*); + virtual void insertedIntoDocument(); + +private: + String m_domain; + String m_path; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLAnchorElement.cpp b/Source/WebCore/wml/WMLAnchorElement.cpp new file mode 100644 index 0000000..5b842bc --- /dev/null +++ b/Source/WebCore/wml/WMLAnchorElement.cpp @@ -0,0 +1,85 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLAnchorElement.h" + +#include "EventNames.h" +#include "KeyboardEvent.h" +#include "WMLTaskElement.h" +#include "HTMLNames.h" + +namespace WebCore { + +WMLAnchorElement::WMLAnchorElement(const QualifiedName& tagName, Document* doc) + : WMLAElement(tagName, doc) + , m_task(0) +{ + // Calling setIsLink(), and returning a non-null value on CSSStyleSelectors' linkAttribute + // method, makes it possible to 'appear as link' (just like <a href="..">) without the need to + // actually set the href value to an empty value in the DOM tree. + setIsLink(); +} + +PassRefPtr<WMLAnchorElement> WMLAnchorElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLAnchorElement(tagName, document)); +} + +WMLAnchorElement::~WMLAnchorElement() +{ +} + +void WMLAnchorElement::defaultEventHandler(Event* event) +{ + bool shouldHandle = false; + + if (event->type() == eventNames().clickEvent) + shouldHandle = true; + else if (event->type() == eventNames().keydownEvent && event->isKeyboardEvent() && focused()) + shouldHandle = static_cast<KeyboardEvent*>(event)->keyIdentifier() == "Enter"; + + if (shouldHandle && m_task) { + m_task->executeTask(); + event->setDefaultHandled(); + return; + } + + // Skip WMLAElement::defaultEventHandler, we don't own a href attribute, that needs to be handled. + WMLElement::defaultEventHandler(event); +} + +void WMLAnchorElement::registerTask(WMLTaskElement* task) +{ + ASSERT(!m_task); + m_task = task; +} + +void WMLAnchorElement::deregisterTask(WMLTaskElement* task) +{ + ASSERT_UNUSED(task, m_task == task); + m_task = 0; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLAnchorElement.h b/Source/WebCore/wml/WMLAnchorElement.h new file mode 100644 index 0000000..6cb36c8 --- /dev/null +++ b/Source/WebCore/wml/WMLAnchorElement.h @@ -0,0 +1,51 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLAnchorElement_h +#define WMLAnchorElement_h + +#if ENABLE(WML) +#include "WMLAElement.h" + +namespace WebCore { + +class WMLTaskElement; + +class WMLAnchorElement : public WMLAElement { +public: + static PassRefPtr<WMLAnchorElement> create(const QualifiedName& tagName, Document*); + + WMLAnchorElement(const QualifiedName& tagName, Document*); + virtual ~WMLAnchorElement(); + + virtual void defaultEventHandler(Event*); + +private: + friend class WMLTaskElement; + void registerTask(WMLTaskElement*); + void deregisterTask(WMLTaskElement*); + + WMLTaskElement* m_task; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLAttributeNames.in b/Source/WebCore/wml/WMLAttributeNames.in new file mode 100644 index 0000000..e2711fb --- /dev/null +++ b/Source/WebCore/wml/WMLAttributeNames.in @@ -0,0 +1,24 @@ +namespace="WML" +namespaceURI="http://www.wapforum.org/DTD/wml_1.1.xml" +guardFactoryWith="ENABLE(WML)" +attrsNullNamespace + +cache_control +columns +domain +emptyok +format +forua +iname +ivalue +localsrc +mode +newcontext +onenterbackward +onenterforward +onpick +ontimer +optional +ordered +path +sendreferer diff --git a/Source/WebCore/wml/WMLBRElement.cpp b/Source/WebCore/wml/WMLBRElement.cpp new file mode 100644 index 0000000..51a2f57 --- /dev/null +++ b/Source/WebCore/wml/WMLBRElement.cpp @@ -0,0 +1,82 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Simon Hausmann <hausmann@kde.org> + * Copyright (C) 2003, 2006 Apple Computer, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLBRElement.h" + +#include "Attribute.h" +#include "CSSPropertyNames.h" +#include "HTMLNames.h" +#include "RenderBR.h" + +namespace WebCore { + +WMLBRElement::WMLBRElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLBRElement> WMLBRElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLBRElement(tagName, document)); +} + +bool WMLBRElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const +{ + if (attrName == HTMLNames::clearAttr) { + result = eUniversal; + return false; + } + + return WMLElement::mapToEntry(attrName, result); +} + +void WMLBRElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::clearAttr) { + // If the string is empty, then don't add the clear property. + // <br clear> and <br clear=""> are just treated like <br> by Gecko, Mac IE, etc. -dwh + const AtomicString& value = attr->value(); + if (value.isEmpty()) + return; + + if (equalIgnoringCase(value, "all")) + addCSSProperty(attr, CSSPropertyClear, "both"); + else + addCSSProperty(attr, CSSPropertyClear, value); + } else + WMLElement::parseMappedAttribute(attr); +} + +RenderObject* WMLBRElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + return new (arena) RenderBR(this); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLBRElement.h b/Source/WebCore/wml/WMLBRElement.h new file mode 100644 index 0000000..fb12688 --- /dev/null +++ b/Source/WebCore/wml/WMLBRElement.h @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * (C) 2000 Simon Hausmann <hausmann@kde.org> + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLBRElement_h +#define WMLBRElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLBRElement : public WMLElement { +public: + static PassRefPtr<WMLBRElement> create(const QualifiedName& tagName, Document*); + + WMLBRElement(const QualifiedName& tagName, Document*); + + virtual bool mapToEntry(const QualifiedName&, MappedAttributeEntry&) const; + virtual void parseMappedAttribute(Attribute*); + + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLCardElement.cpp b/Source/WebCore/wml/WMLCardElement.cpp new file mode 100644 index 0000000..38ba8ab --- /dev/null +++ b/Source/WebCore/wml/WMLCardElement.cpp @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLCardElement.h" + +#include "Attribute.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "HTMLNames.h" +#include "NodeList.h" +#include "Page.h" +#include "RenderStyle.h" +#include "WMLDoElement.h" +#include "WMLDocument.h" +#include "WMLInputElement.h" +#include "WMLIntrinsicEventHandler.h" +#include "WMLNames.h" +#include "WMLSelectElement.h" +#include "WMLTemplateElement.h" +#include "WMLTimerElement.h" +#include "WMLVariables.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLCardElement::WMLCardElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) + , m_isNewContext(false) + , m_isOrdered(false) + , m_isVisible(false) + , m_eventTimer(0) + , m_template(0) +{ + ASSERT(hasTagName(cardTag)); +} + +PassRefPtr<WMLCardElement> WMLCardElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLCardElement(tagName, document)); +} + +WMLCardElement::~WMLCardElement() +{ +} + +void WMLCardElement::showCard() +{ + ASSERT(attached()); + + if (m_isVisible) { + ASSERT(renderer()); + return; + } + + m_isVisible = true; + ASSERT(!renderer()); + + detach(); + attach(); + + ASSERT(attached()); + ASSERT(renderer()); +} + +void WMLCardElement::hideCard() +{ + ASSERT(attached()); + + if (!m_isVisible) { + ASSERT(!renderer()); + return; + } + + m_isVisible = false; + ASSERT(renderer()); + + detach(); + attach(); + + ASSERT(attached()); + ASSERT(!renderer()); +} + +void WMLCardElement::setTemplateElement(WMLTemplateElement* temp) +{ + // Only one template is allowed to be attached to a card + if (m_template) { + reportWMLError(document(), WMLErrorMultipleTemplateElements); + return; + } + + m_template = temp; +} + +void WMLCardElement::setIntrinsicEventTimer(WMLTimerElement* timer) +{ + // Only one timer is allowed in a card + if (m_eventTimer) { + reportWMLError(document(), WMLErrorMultipleTimerElements); + return; + } + + m_eventTimer = timer; +} + +void WMLCardElement::handleIntrinsicEventIfNeeded() +{ + WMLPageState* pageState = wmlPageStateForDocument(document()); + if (!pageState) + return; + + Frame* frame = document()->frame(); + if (!frame) + return; + + FrameLoader* loader = frame->loader(); + if (!loader) + return; + + // Calculate the entry method of current card + WMLIntrinsicEventType eventType = WMLIntrinsicEventUnknown; + + switch (loader->policyChecker()->loadType()) { + case FrameLoadTypeReload: + break; + case FrameLoadTypeBack: + eventType = WMLIntrinsicEventOnEnterBackward; + break; + case FrameLoadTypeBackWMLDeckNotAccessible: + reportWMLError(document(), WMLErrorDeckNotAccessible); + return; + default: + eventType = WMLIntrinsicEventOnEnterForward; + break; + } + + // Figure out target event handler + WMLIntrinsicEventHandler* eventHandler = this->eventHandler(); + bool hasIntrinsicEvent = false; + + if (eventType != WMLIntrinsicEventUnknown) { + if (eventHandler && eventHandler->hasIntrinsicEvent(eventType)) + hasIntrinsicEvent = true; + else if (m_template) { + eventHandler = m_template->eventHandler(); + if (eventHandler && eventHandler->hasIntrinsicEvent(eventType)) + hasIntrinsicEvent = true; + } + } + + if (hasIntrinsicEvent) + eventHandler->triggerIntrinsicEvent(eventType); + + // Start the timer if it exists in current card + if (m_eventTimer) + m_eventTimer->start(); + + for (Node* node = traverseNextNode(); node != 0; node = node->traverseNextNode()) { + if (!node->isElementNode()) + continue; + + if (node->hasTagName(inputTag)) + static_cast<WMLInputElement*>(node)->initialize(); + else if (node->hasTagName(selectTag)) + static_cast<WMLSelectElement*>(node)->selectInitialOptions(); + } +} + +void WMLCardElement::handleDeckLevelTaskOverridesIfNeeded() +{ + // Spec: The event-handling element may appear inside a template element and specify + // event-processing behaviour for all cards in the deck. A deck-level event-handling + // element is equivalent to specifying the event-handling element in each card. + if (!m_template) + return; + + Vector<WMLDoElement*>& templateDoElements = m_template->doElements(); + if (templateDoElements.isEmpty()) + return; + + Vector<WMLDoElement*>& cardDoElements = doElements(); + Vector<WMLDoElement*>::iterator it = cardDoElements.begin(); + Vector<WMLDoElement*>::iterator end = cardDoElements.end(); + + HashSet<String> cardDoElementNames; + for (; it != end; ++it) + cardDoElementNames.add((*it)->name()); + + it = templateDoElements.begin(); + end = templateDoElements.end(); + + for (; it != end; ++it) + (*it)->setActive(!cardDoElementNames.contains((*it)->name())); +} + +void WMLCardElement::parseMappedAttribute(Attribute* attr) +{ + WMLIntrinsicEventType eventType = WMLIntrinsicEventUnknown; + + if (attr->name() == onenterforwardAttr) + eventType = WMLIntrinsicEventOnEnterForward; + else if (attr->name() == onenterbackwardAttr) + eventType = WMLIntrinsicEventOnEnterBackward; + else if (attr->name() == ontimerAttr) + eventType = WMLIntrinsicEventOnTimer; + else if (attr->name() == newcontextAttr) + m_isNewContext = (attr->value() == "true"); + else if (attr->name() == orderedAttr) + m_isOrdered = (attr->value() == "true"); + else { + WMLElement::parseMappedAttribute(attr); + return; + } + + if (eventType == WMLIntrinsicEventUnknown) + return; + + // Register intrinsic event in card + RefPtr<WMLIntrinsicEvent> event = WMLIntrinsicEvent::create(document(), attr->value()); + + createEventHandlerIfNeeded(); + eventHandler()->registerIntrinsicEvent(eventType, event); +} + +void WMLCardElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + Document* document = this->document(); + + // The first card inserted into a document, is visible by default. + if (!m_isVisible) { + RefPtr<NodeList> nodeList = document->getElementsByTagName("card"); + if (nodeList && nodeList->length() == 1 && nodeList->item(0) == this) + m_isVisible = true; + } + + // For the WML layout tests we embed WML content in a XHTML document. Navigating to different cards + // within the same deck has a different behaviour in HTML than in WML. HTML wants to "scroll to anchor" + // (see FrameLoader) but WML wants a reload. Notify the root document of the layout test that we want + // to mimic WML behaviour. This is rather tricky, but has been tested extensively. Usually it's not possible + // at all to embed WML in HTML, it's not designed that way, we're just "abusing" it for dynamically created layout tests. + if (document->page() && document->page()->mainFrame()) { + Document* rootDocument = document->page()->mainFrame()->document(); + if (rootDocument && rootDocument != document) + rootDocument->setContainsWMLContent(true); + } +} + +RenderObject* WMLCardElement::createRenderer(RenderArena* arena, RenderStyle* style) +{ + if (!m_isVisible) { + style->setUnique(); + style->setDisplay(NONE); + } + + return WMLElement::createRenderer(arena, style); +} + +WMLCardElement* WMLCardElement::findNamedCardInDocument(Document* doc, const String& cardName) +{ + if (cardName.isEmpty()) + return 0; + + RefPtr<NodeList> nodeList = doc->getElementsByTagName("card"); + if (!nodeList) + return 0; + + unsigned length = nodeList->length(); + if (length < 1) + return 0; + + for (unsigned i = 0; i < length; ++i) { + WMLCardElement* card = static_cast<WMLCardElement*>(nodeList->item(i)); + if (card->getIdAttribute() != cardName) + continue; + + return card; + } + + return 0; +} + +WMLCardElement* WMLCardElement::determineActiveCard(Document* doc) +{ + WMLPageState* pageState = wmlPageStateForDocument(doc); + if (!pageState) + return 0; + + RefPtr<NodeList> nodeList = doc->getElementsByTagName("card"); + if (!nodeList) + return 0; + + unsigned length = nodeList->length(); + if (length < 1) + return 0; + + // Figure out the new target card + String cardName = doc->url().fragmentIdentifier(); + + WMLCardElement* activeCard = findNamedCardInDocument(doc, cardName); + if (activeCard) { + // Hide all cards - except the destination card - in document + for (unsigned i = 0; i < length; ++i) { + WMLCardElement* card = static_cast<WMLCardElement*>(nodeList->item(i)); + + if (card == activeCard) + card->showCard(); + else + card->hideCard(); + } + } else { + // If the target URL didn't contain a fragment identifier, activeCard + // is 0, and has to be set to the first card element in the deck. + activeCard = static_cast<WMLCardElement*>(nodeList->item(0)); + activeCard->showCard(); + } + + // Assure destination card is visible + ASSERT(activeCard->isVisible()); + ASSERT(activeCard->attached()); + ASSERT(activeCard->renderer()); + + // Update the document title + doc->setTitle(activeCard->title()); + + return activeCard; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLCardElement.h b/Source/WebCore/wml/WMLCardElement.h new file mode 100644 index 0000000..f82374d --- /dev/null +++ b/Source/WebCore/wml/WMLCardElement.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLCardElement_h +#define WMLCardElement_h + +#if ENABLE(WML) +#include "WMLEventHandlingElement.h" + +#include <wtf/Vector.h> + +namespace WebCore { + +class WMLTemplateElement; +class WMLTimerElement; + +class WMLCardElement : public WMLElement, public WMLEventHandlingElement { +public: + static PassRefPtr<WMLCardElement> create(const QualifiedName& tagName, Document*); + + WMLCardElement(const QualifiedName&, Document*); + virtual ~WMLCardElement(); + + bool isNewContext() const { return m_isNewContext; } + bool isOrdered() const { return m_isOrdered; } + WMLTimerElement* eventTimer() const { return m_eventTimer; } + WMLTemplateElement* templateElement() const { return m_template; } + + void setTemplateElement(WMLTemplateElement*); + void setIntrinsicEventTimer(WMLTimerElement*); + + void handleIntrinsicEventIfNeeded(); + void handleDeckLevelTaskOverridesIfNeeded(); + + virtual void parseMappedAttribute(Attribute*); + virtual void insertedIntoDocument(); + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + + // Switch active card in document to the one specified in the URL reference (foo.wml#mycard) + // If the 'targetUrl' doesn't contain a reference, use the first <card> element in the document. + static WMLCardElement* determineActiveCard(Document*); + static WMLCardElement* findNamedCardInDocument(Document*, const String& cardName); + +private: + bool isVisible() const { return m_isVisible; } + + void showCard(); + void hideCard(); + + bool m_isNewContext; + bool m_isOrdered; + bool m_isVisible; + + WMLTimerElement* m_eventTimer; + WMLTemplateElement* m_template; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLDoElement.cpp b/Source/WebCore/wml/WMLDoElement.cpp new file mode 100644 index 0000000..a8d4880 --- /dev/null +++ b/Source/WebCore/wml/WMLDoElement.cpp @@ -0,0 +1,195 @@ +/** + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLDoElement.h" + +#include "Attribute.h" +#include "BackForwardController.h" +#include "Event.h" +#include "EventNames.h" +#include "HTMLNames.h" +#include "KeyboardEvent.h" +#include "Page.h" +#include "RenderButton.h" +#include "WMLCardElement.h" +#include "WMLDocument.h" +#include "WMLNames.h" +#include "WMLPageState.h" +#include "WMLTaskElement.h" +#include "WMLTimerElement.h" +#include "WMLVariables.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLDoElement::WMLDoElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) + , m_task(0) + , m_isActive(false) + , m_isNoop(false) + , m_isOptional(false) +{ +} + +PassRefPtr<WMLDoElement> WMLDoElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLDoElement(tagName, document)); +} + +void WMLDoElement::defaultEventHandler(Event* event) +{ + if (m_isOptional) + return; + + if (event->type() == eventNames().keypressEvent) { + WMLElement::defaultEventHandler(event); + return; + } + + if (event->type() != eventNames().clickEvent && event->type() != eventNames().keydownEvent) + return; + + if (event->isKeyboardEvent() + && static_cast<KeyboardEvent*>(event)->keyIdentifier() != "Enter") + return; + + if (m_type == "accept" || m_type == "options") { + if (m_task) + m_task->executeTask(); + } else if (m_type == "prev") { + ASSERT(document()->isWMLDocument()); + WMLDocument* document = static_cast<WMLDocument*>(this->document()); + + WMLPageState* pageState = wmlPageStateForDocument(document); + if (!pageState) + return; + + // Stop the timer of the current card if it is active + if (WMLCardElement* card = document->activeCard()) { + if (WMLTimerElement* eventTimer = card->eventTimer()) + eventTimer->stop(); + } + + pageState->page()->backForward()->goBack(); + } else if (m_type == "reset") { + WMLPageState* pageState = wmlPageStateForDocument(document()); + if (!pageState) + return; + + pageState->reset(); + } +} + +void WMLDoElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::typeAttr) + m_type = parseValueForbiddingVariableReferences(attr->value()); + else if (attr->name() == HTMLNames::nameAttr) + m_name = parseValueForbiddingVariableReferences(attr->value()); + else if (attr->name() == optionalAttr) + m_isOptional = (attr->value() == "true"); + else + WMLElement::parseMappedAttribute(attr); +} + +void WMLDoElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + // Spec: An unspecified 'name' defaults to the value of the 'type' attribute. + if (!hasAttribute(HTMLNames::nameAttr)) + m_name = m_type; + + ContainerNode* parent = parentNode(); + if (!parent || !parent->isWMLElement()) + return; + + if (WMLEventHandlingElement* eventHandlingElement = toWMLEventHandlingElement(static_cast<WMLElement*>(parent))) + eventHandlingElement->registerDoElement(this, document()); +} + +void WMLDoElement::removedFromDocument() +{ + ContainerNode* parent = parentNode(); + + if (parent && parent->isWMLElement()) { + if (WMLEventHandlingElement* eventHandlingElement = toWMLEventHandlingElement(static_cast<WMLElement*>(parent))) + eventHandlingElement->deregisterDoElement(this); + } + + WMLElement::removedFromDocument(); +} + +void WMLDoElement::attach() +{ + WMLElement::attach(); + + // The call to updateFromElement() needs to go after the call through + // to the base class's attach() because that can sometimes do a close + // on the renderer. + if (renderer()) + renderer()->updateFromElement(); +} + +RenderObject* WMLDoElement::createRenderer(RenderArena* arena, RenderStyle* style) +{ + if (!m_isActive || m_isOptional || m_isNoop) + return 0; + + if (style) { + style->setUnique(); + style->setBackgroundColor(Color::lightGray); + } + + return new (arena) RenderButton(this); +} + +void WMLDoElement::recalcStyle(StyleChange change) +{ + WMLElement::recalcStyle(change); + + if (renderer()) + renderer()->updateFromElement(); +} + +void WMLDoElement::registerTask(WMLTaskElement* task) +{ + ASSERT(!m_task); + m_task = task; +} + +void WMLDoElement::deregisterTask(WMLTaskElement* task) +{ + ASSERT_UNUSED(task, m_task == task); + m_task = 0; +} + +String WMLDoElement::label() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::labelAttr)); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLDoElement.h b/Source/WebCore/wml/WMLDoElement.h new file mode 100644 index 0000000..2ba6d9e --- /dev/null +++ b/Source/WebCore/wml/WMLDoElement.h @@ -0,0 +1,68 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLDoElement_h +#define WMLDoElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLTaskElement; + +class WMLDoElement : public WMLElement { +public: + static PassRefPtr<WMLDoElement> create(const QualifiedName& tagName, Document*); + + WMLDoElement(const QualifiedName& tagName, Document*); + + virtual void defaultEventHandler(Event*); + virtual void parseMappedAttribute(Attribute*); + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + + virtual void attach(); + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual void recalcStyle(StyleChange); + + void registerTask(WMLTaskElement*); + void deregisterTask(WMLTaskElement*); + + bool isActive() const { return m_isActive; } + String label() const; + String name() const { return m_name; } + + void setActive(bool active) { m_isActive = active; } + void setNoop(bool noop) { m_isNoop = noop;} + +private: + WMLTaskElement* m_task; + bool m_isActive; + bool m_isNoop; + bool m_isOptional; + String m_name; + String m_type; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLDocument.cpp b/Source/WebCore/wml/WMLDocument.cpp new file mode 100644 index 0000000..9b29899 --- /dev/null +++ b/Source/WebCore/wml/WMLDocument.cpp @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLDocument.h" + +#include "BackForwardController.h" +#include "BackForwardList.h" +#include "Frame.h" +#include "Page.h" +#include "ScriptableDocumentParser.h" +#include "WMLCardElement.h" +#include "WMLErrorHandling.h" +#include "WMLPageState.h" +#include "WMLTemplateElement.h" + +namespace WebCore { + +WMLDocument::WMLDocument(Frame* frame, const KURL& url) + : Document(frame, url, false, false) + , m_activeCard(0) +{ + clearXMLVersion(); +} + +WMLDocument::~WMLDocument() +{ +} + +void WMLDocument::finishedParsing() +{ + if (ScriptableDocumentParser* parser = this->scriptableDocumentParser()) { + if (!parser->wellFormed()) { + Document::finishedParsing(); + return; + } + } + + bool hasAccess = initialize(true); + Document::finishedParsing(); + + if (!hasAccess) { + m_activeCard = 0; + + WMLPageState* wmlPageState = wmlPageStateForDocument(this); + if (!wmlPageState) + return; + + Page* page = wmlPageState->page(); + if (!page) + return; + + HistoryItem* item = page->backForward()->backItem(); + if (!item) + return; + + page->goToItem(item, FrameLoadTypeBackWMLDeckNotAccessible); + return; + } + + if (m_activeCard) + m_activeCard->handleIntrinsicEventIfNeeded(); +} + +bool WMLDocument::initialize(bool aboutToFinishParsing) +{ + WMLPageState* wmlPageState = wmlPageStateForDocument(this); + if (!wmlPageState || !wmlPageState->canAccessDeck()) + return false; + + // Remember that we'e successfully entered the deck + wmlPageState->resetAccessControlData(); + + // Notify the existance of templates to all cards of the current deck + WMLTemplateElement::registerTemplatesInDocument(this); + + // Set destination card + m_activeCard = WMLCardElement::determineActiveCard(this); + if (!m_activeCard) { + reportWMLError(this, WMLErrorNoCardInDocument); + return true; + } + + // Handle deck-level task overrides + m_activeCard->handleDeckLevelTaskOverridesIfNeeded(); + + // Handle card-level intrinsic event + if (!aboutToFinishParsing) + m_activeCard->handleIntrinsicEventIfNeeded(); + + return true; +} + +WMLPageState* wmlPageStateForDocument(Document* doc) +{ + ASSERT(doc); + + Page* page = doc->page(); + ASSERT(page); + + return page->wmlPageState(); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLDocument.h b/Source/WebCore/wml/WMLDocument.h new file mode 100644 index 0000000..3057d9b --- /dev/null +++ b/Source/WebCore/wml/WMLDocument.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLDocument_h +#define WMLDocument_h + +#if ENABLE(WML) +#include "Document.h" +#include "WMLErrorHandling.h" +#include "WMLPageState.h" + +namespace WebCore { + +class WMLCardElement; + +class WMLDocument : public Document { +public: + static PassRefPtr<WMLDocument> create(Frame* frame, const KURL& url) + { + return adoptRef(new WMLDocument(frame, url)); + } + + virtual ~WMLDocument(); + + virtual bool isWMLDocument() const { return true; } + virtual void finishedParsing(); + + bool initialize(bool aboutToFinishParsing = false); + + WMLCardElement* activeCard() const { return m_activeCard; } + +private: + WMLDocument(Frame*, const KURL&); + WMLCardElement* m_activeCard; +}; + +WMLPageState* wmlPageStateForDocument(Document*); + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLElement.cpp b/Source/WebCore/wml/WMLElement.cpp new file mode 100644 index 0000000..9b0be47 --- /dev/null +++ b/Source/WebCore/wml/WMLElement.cpp @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLElement.h" + +#include "Attribute.h" +#include "CSSPropertyNames.h" +#include "HTMLNames.h" +#include "HTMLParserIdioms.h" +#include "RenderObject.h" +#include "WMLErrorHandling.h" +#include "WMLNames.h" +#include "WMLVariables.h" + +using std::max; +using std::min; + +namespace WebCore { + +using namespace WMLNames; + +WMLElement::WMLElement(const QualifiedName& tagName, Document* document) + : StyledElement(tagName, document, CreateStyledElement) +{ +} + +PassRefPtr<WMLElement> WMLElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLElement(tagName, document)); +} + +bool WMLElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const +{ + if (attrName == HTMLNames::alignAttr) { + result = eUniversal; + return false; + } + + return StyledElement::mapToEntry(attrName, result); +} + +void WMLElement::parseMappedAttribute(Attribute* attr) +{ + if (isIdAttributeName(attr->name()) + || attr->name() == HTMLNames::classAttr + || attr->name() == HTMLNames::styleAttr) + return StyledElement::parseMappedAttribute(attr); + + if (attr->name() == HTMLNames::alignAttr) { + if (equalIgnoringCase(attr->value(), "middle")) + addCSSProperty(attr, CSSPropertyTextAlign, "center"); + else + addCSSProperty(attr, CSSPropertyTextAlign, attr->value()); + } else if (attr->name() == HTMLNames::tabindexAttr) { + String indexstring = attr->value(); + int tabindex = 0; + if (parseHTMLInteger(indexstring, tabindex)) { + // Clamp tabindex to the range of 'short' to match Firefox's behavior. + setTabIndexExplicitly(max(static_cast<int>(std::numeric_limits<short>::min()), min(tabindex, static_cast<int>(std::numeric_limits<short>::max())))); + } + } +} + +String WMLElement::title() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::titleAttr)); +} + +bool WMLElement::rendererIsNeeded(RenderStyle* style) +{ + return document()->documentElement() == this || style->display() != NONE; +} + +RenderObject* WMLElement::createRenderer(RenderArena*, RenderStyle* style) +{ + return RenderObject::createObject(this, style); +} + +String WMLElement::parseValueSubstitutingVariableReferences(const AtomicString& value, WMLErrorCode defaultErrorCode) const +{ + bool isValid = false; + if (!containsVariableReference(value, isValid)) + return value; + + if (!isValid) { + reportWMLError(document(), defaultErrorCode); + return String(); + } + + return substituteVariableReferences(value, document()); +} + +String WMLElement::parseValueForbiddingVariableReferences(const AtomicString& value) const +{ + bool isValid = false; + if (containsVariableReference(value, isValid)) { + reportWMLError(document(), WMLErrorInvalidVariableReferenceLocation); + return String(); + } + + return value; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLElement.h b/Source/WebCore/wml/WMLElement.h new file mode 100644 index 0000000..a7c82c0 --- /dev/null +++ b/Source/WebCore/wml/WMLElement.h @@ -0,0 +1,56 @@ +/* + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLElement_h +#define WMLElement_h + +#if ENABLE(WML) +#include "StyledElement.h" +#include "WMLErrorHandling.h" + +namespace WebCore { + +class WMLElement : public StyledElement { +public: + static PassRefPtr<WMLElement> create(const QualifiedName& tagName, Document*); + + virtual bool isWMLElement() const { return true; } + virtual bool isWMLTaskElement() const { return false; } + + virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const; + virtual void parseMappedAttribute(Attribute*); + + virtual String title() const; + + virtual bool rendererIsNeeded(RenderStyle*); + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + +protected: + WMLElement(const QualifiedName& tagName, Document*); + + // Helper function for derived classes + String parseValueSubstitutingVariableReferences(const AtomicString&, WMLErrorCode defaultErrorCode = WMLErrorInvalidVariableReference) const; + String parseValueForbiddingVariableReferences(const AtomicString&) const; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLErrorHandling.cpp b/Source/WebCore/wml/WMLErrorHandling.cpp new file mode 100644 index 0000000..a49a71b --- /dev/null +++ b/Source/WebCore/wml/WMLErrorHandling.cpp @@ -0,0 +1,106 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLErrorHandling.h" + +#include "Console.h" +#include "Frame.h" +#include "Document.h" +#include "DOMWindow.h" +#include "XMLDocumentParser.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +void reportWMLError(Document* doc, WMLErrorCode error) +{ + if (!doc || error == WMLErrorUnknown) + return; + + String errorMessage = errorMessageForErrorCode(error); + XMLDocumentParser* parser = static_cast<XMLDocumentParser*>(doc->parser()); + if (parser && error != WMLErrorDeckNotAccessible) { + // Some errors are reported as result of an insertedIntoDocument() call. + // If this happened, parsing has been stopped, and the document fragment + // is wrapped in a XHTML error document. That means insertedIntoDocument() + // will be called again - do NOT report the error twice, that would result + // in an infinite error reporting loop. + if (!parser->wellFormed()) + return; + + parser->handleError(XMLDocumentParser::fatal, errorMessage.latin1().data(), parser->textPositionOneBased()); + } else { + Frame* frame = doc->frame(); + if (!frame) + return; + + DOMWindow* domWindow = frame->domWindow(); + if (!domWindow) + return; + + Console* console = domWindow->console(); + if (!console) + return; + + console->addMessage(WMLMessageSource, LogMessageType, ErrorMessageLevel, errorMessage, 0, String()); + } +} + +String errorMessageForErrorCode(WMLErrorCode error) +{ + switch (error) { + case WMLErrorConflictingEventBinding: + return "Conflicting event bindings within an element."; + case WMLErrorDeckNotAccessible: + return "Deck not accessible."; + case WMLErrorDuplicatedDoElement: + return "At least two do elements share a name, which is not allowed."; + case WMLErrorForbiddenTaskInAnchorElement: + return "Forbidden task contained in anchor element."; + case WMLErrorInvalidColumnsNumberInTable: + return "A table contains an invalid number of columns."; + case WMLErrorInvalidVariableName: + return "A variable name contains invalid characters."; + case WMLErrorInvalidVariableReference: + return "A variable reference uses invalid syntax."; + case WMLErrorInvalidVariableReferenceLocation: + return "A variable reference is placed in an invalid location."; + case WMLErrorMultipleAccessElements: + return "Only one access element is allowed in a deck."; + case WMLErrorMultipleTemplateElements: + return "Only one template element is allowed in a deck."; + case WMLErrorNoCardInDocument: + return "No card contained in document."; + case WMLErrorMultipleTimerElements: + return "Only one timer element is allowed in a card."; + case WMLErrorUnknown: + return String(); + }; + + ASSERT_NOT_REACHED(); + return String(); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLErrorHandling.h b/Source/WebCore/wml/WMLErrorHandling.h new file mode 100644 index 0000000..c75c975 --- /dev/null +++ b/Source/WebCore/wml/WMLErrorHandling.h @@ -0,0 +1,52 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLErrorHandling_h +#define WMLErrorHandling_h + +#include <wtf/Forward.h> + +#if ENABLE(WML) +namespace WebCore { + + class Document; + + enum WMLErrorCode { + WMLErrorUnknown = 0, + WMLErrorConflictingEventBinding, + WMLErrorDeckNotAccessible, + WMLErrorDuplicatedDoElement, + WMLErrorForbiddenTaskInAnchorElement, + WMLErrorInvalidColumnsNumberInTable, + WMLErrorInvalidVariableName, + WMLErrorInvalidVariableReference, + WMLErrorInvalidVariableReferenceLocation, + WMLErrorMultipleAccessElements, + WMLErrorMultipleTemplateElements, + WMLErrorMultipleTimerElements, + WMLErrorNoCardInDocument + }; + + String errorMessageForErrorCode(WMLErrorCode); + void reportWMLError(Document*, WMLErrorCode); +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLEventHandlingElement.cpp b/Source/WebCore/wml/WMLEventHandlingElement.cpp new file mode 100644 index 0000000..faa80c7 --- /dev/null +++ b/Source/WebCore/wml/WMLEventHandlingElement.cpp @@ -0,0 +1,97 @@ +/** + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLEventHandlingElement.h" + +#include "WMLCardElement.h" +#include "WMLDoElement.h" +#include "WMLIntrinsicEventHandler.h" +#include "WMLOptionElement.h" +#include "WMLTaskElement.h" +#include "WMLTemplateElement.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLEventHandlingElement::WMLEventHandlingElement() +{ +} + +WMLEventHandlingElement::~WMLEventHandlingElement() +{ +} + +void WMLEventHandlingElement::createEventHandlerIfNeeded() +{ + if (!m_eventHandler) + m_eventHandler.set(new WMLIntrinsicEventHandler); +} + +void WMLEventHandlingElement::registerDoElement(WMLDoElement* doElement, Document* document) +{ + Vector<WMLDoElement*>::iterator it = m_doElements.begin(); + Vector<WMLDoElement*>::iterator end = m_doElements.end(); + + for (; it != end; ++it) { + if ((*it)->name() == doElement->name()) { + reportWMLError(document, WMLErrorDuplicatedDoElement); + return; + } + } + + ASSERT(m_doElements.find(doElement) == WTF::notFound); + m_doElements.append(doElement); + doElement->setActive(true); +} + +void WMLEventHandlingElement::deregisterDoElement(WMLDoElement* doElement) +{ + doElement->setActive(false); + + size_t position = m_doElements.find(doElement); + if (position == WTF::notFound) + return; + + m_doElements.remove(position); +} + +WMLEventHandlingElement* toWMLEventHandlingElement(WMLElement* element) +{ + if (!element->isWMLElement()) + return 0; + + if (element->hasTagName(cardTag)) + return static_cast<WMLCardElement*>(element); + else if (element->hasTagName(optionTag)) + return static_cast<WMLOptionElement*>(element); + else if (element->hasTagName(templateTag)) + return static_cast<WMLTemplateElement*>(element); + + return 0; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLEventHandlingElement.h b/Source/WebCore/wml/WMLEventHandlingElement.h new file mode 100644 index 0000000..15cef7b --- /dev/null +++ b/Source/WebCore/wml/WMLEventHandlingElement.h @@ -0,0 +1,57 @@ +/** + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLEventHandlingElement_h +#define WMLEventHandlingElement_h + +#if ENABLE(WML) +#include "WMLIntrinsicEventHandler.h" + +#include <wtf/OwnPtr.h> +#include <wtf/Vector.h> + +namespace WebCore { + +class WMLElement; +class WMLDoElement; + +class WMLEventHandlingElement { +public: + WMLEventHandlingElement(); + ~WMLEventHandlingElement(); + + WMLIntrinsicEventHandler* eventHandler() const { return m_eventHandler.get(); } + void createEventHandlerIfNeeded(); + + Vector<WMLDoElement*>& doElements() { return m_doElements; } + void registerDoElement(WMLDoElement*, Document*); + void deregisterDoElement(WMLDoElement*); + +private: + OwnPtr<WMLIntrinsicEventHandler> m_eventHandler; + Vector<WMLDoElement*> m_doElements; +}; + +WMLEventHandlingElement* toWMLEventHandlingElement(WMLElement*); + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLFieldSetElement.cpp b/Source/WebCore/wml/WMLFieldSetElement.cpp new file mode 100644 index 0000000..86c1e46 --- /dev/null +++ b/Source/WebCore/wml/WMLFieldSetElement.cpp @@ -0,0 +1,85 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLFieldSetElement.h" + +#include "Attribute.h" +#include "HTMLNames.h" +#include "RenderFieldset.h" +#include "Text.h" +#include "WMLElementFactory.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLFieldSetElement::WMLFieldSetElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLFieldSetElement> WMLFieldSetElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLFieldSetElement(tagName, document)); +} + +WMLFieldSetElement::~WMLFieldSetElement() +{ +} + +void WMLFieldSetElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + String title = parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::titleAttr)); + if (title.isEmpty()) + return; + + m_insertedLegendElement = WMLElementFactory::createWMLElement(insertedLegendTag, document()); + + // Insert <dummyLegend> element, as RenderFieldset expect it to be present + // to layout it's child text content, when rendering <fieldset> elements + ExceptionCode ec = 0; + appendChild(m_insertedLegendElement, ec); + ASSERT(ec == 0); + + // Create text node holding the 'title' attribute value + m_insertedLegendElement->appendChild(document()->createTextNode(title), ec); + ASSERT(ec == 0); +} + +void WMLFieldSetElement::removedFromDocument() +{ + m_insertedLegendElement.clear(); + WMLElement::removedFromDocument(); +} + +RenderObject* WMLFieldSetElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + return new (arena) RenderFieldset(this); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLFieldSetElement.h b/Source/WebCore/wml/WMLFieldSetElement.h new file mode 100644 index 0000000..11ef2c1 --- /dev/null +++ b/Source/WebCore/wml/WMLFieldSetElement.h @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLFieldSetElement_h +#define WMLFieldSetElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLFieldSetElement : public WMLElement { +public: + static PassRefPtr<WMLFieldSetElement> create(const QualifiedName&, Document*); + + WMLFieldSetElement(const QualifiedName& tagName, Document*); + virtual ~WMLFieldSetElement(); + + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + +private: + RefPtr<WMLElement> m_insertedLegendElement; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLFormControlElement.cpp b/Source/WebCore/wml/WMLFormControlElement.cpp new file mode 100644 index 0000000..c264340 --- /dev/null +++ b/Source/WebCore/wml/WMLFormControlElement.cpp @@ -0,0 +1,86 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLFormControlElement.h" + +#include "RenderBox.h" +#include "RenderObject.h" +#include "RenderStyle.h" + +namespace WebCore { + +WMLFormControlElement::WMLFormControlElement(const QualifiedName& tagName, Document* document) + : WMLElement(tagName, document) + , m_valueMatchesRenderer(false) +{ +} + +PassRefPtr<WMLFormControlElement> WMLFormControlElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLFormControlElement(tagName, document)); +} + +WMLFormControlElement::~WMLFormControlElement() +{ +} + +bool WMLFormControlElement::supportsFocus() const +{ + return true; +} + +bool WMLFormControlElement::isFocusable() const +{ + if (!renderer() || !renderer()->isBox()) + return false; + + if (toRenderBox(renderer())->size().isEmpty()) + return false; + + return WMLElement::isFocusable(); +} + + +void WMLFormControlElement::attach() +{ + ASSERT(!attached()); + WMLElement::attach(); + + // The call to updateFromElement() needs to go after the call through + // to the base class's attach() because that can sometimes do a close + // on the renderer. + if (renderer()) + renderer()->updateFromElement(); +} + +void WMLFormControlElement::recalcStyle(StyleChange change) +{ + WMLElement::recalcStyle(change); + + if (renderer()) + renderer()->updateFromElement(); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLFormControlElement.h b/Source/WebCore/wml/WMLFormControlElement.h new file mode 100644 index 0000000..674303b --- /dev/null +++ b/Source/WebCore/wml/WMLFormControlElement.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLFormControlElement_h +#define WMLFormControlElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLFormControlElement : public WMLElement { +public: + static PassRefPtr<WMLFormControlElement> create(const QualifiedName&, Document*); + + + virtual ~WMLFormControlElement(); + + virtual bool isFormControlElement() const { return true; } + virtual bool isReadOnlyFormControl() const { return false; } + virtual bool isTextFormControl() const { return false; } + + virtual bool formControlValueMatchesRenderer() const { return m_valueMatchesRenderer; } + virtual void setFormControlValueMatchesRenderer(bool b = true) { m_valueMatchesRenderer = b; } + + virtual bool supportsFocus() const; + virtual bool isFocusable() const; + + virtual void attach(); + virtual void recalcStyle(StyleChange); + +protected: + WMLFormControlElement(const QualifiedName&, Document*); + +private: + bool m_valueMatchesRenderer; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLGoElement.cpp b/Source/WebCore/wml/WMLGoElement.cpp new file mode 100644 index 0000000..cc41226 --- /dev/null +++ b/Source/WebCore/wml/WMLGoElement.cpp @@ -0,0 +1,229 @@ +/** + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLGoElement.h" + +#include "Attribute.h" +#include "FormData.h" +#include "FormDataBuilder.h" +#include "FormSubmission.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "HTMLNames.h" +#include "ResourceRequest.h" +#include "TextEncoding.h" +#include "WMLCardElement.h" +#include "WMLDocument.h" +#include "WMLNames.h" +#include "WMLPageState.h" +#include "WMLPostfieldElement.h" +#include "WMLTimerElement.h" +#include "WMLVariables.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +using namespace WMLNames; + +WMLGoElement::WMLGoElement(const QualifiedName& tagName, Document* doc) + : WMLTaskElement(tagName, doc) +{ +} + +PassRefPtr<WMLGoElement> WMLGoElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLGoElement(tagName, document)); +} + +void WMLGoElement::registerPostfieldElement(WMLPostfieldElement* postfield) +{ + ASSERT(m_postfieldElements.find(postfield) == WTF::notFound); + m_postfieldElements.append(postfield); +} + +void WMLGoElement::deregisterPostfieldElement(WMLPostfieldElement* postfield) +{ + size_t position = m_postfieldElements.find(postfield); + ASSERT(position != WTF::notFound); + m_postfieldElements.remove(position); +} + +void WMLGoElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::methodAttr) + m_formAttributes.parseMethodType(attr->value()); + else if (attr->name() == HTMLNames::enctypeAttr) + m_formAttributes.parseEncodingType(parseValueSubstitutingVariableReferences(attr->value())); + else if (attr->name() == HTMLNames::accept_charsetAttr) + m_formAttributes.setAcceptCharset(parseValueForbiddingVariableReferences(attr->value())); + else + WMLTaskElement::parseMappedAttribute(attr); +} + +void WMLGoElement::executeTask() +{ + ASSERT(document()->isWMLDocument()); + WMLDocument* document = static_cast<WMLDocument*>(this->document()); + + WMLPageState* pageState = wmlPageStateForDocument(document); + if (!pageState) + return; + + WMLCardElement* card = document->activeCard(); + if (!card) + return; + + Frame* frame = document->frame(); + if (!frame) + return; + + FrameLoader* loader = frame->loader(); + if (!loader) + return; + + String href = getAttribute(HTMLNames::hrefAttr); + if (href.isEmpty()) + return; + + // Substitute variables within target url attribute value + KURL url = document->completeURL(substituteVariableReferences(href, document, WMLVariableEscapingEscape)); + if (url.isEmpty()) + return; + + storeVariableState(pageState); + + // Stop the timer of the current card if it is active + if (WMLTimerElement* eventTimer = card->eventTimer()) + eventTimer->stop(); + + // FIXME: 'newcontext' handling not implemented for external cards + bool inSameDeck = document->url().path() == url.path(); + if (inSameDeck && url.hasFragmentIdentifier()) { + if (WMLCardElement* card = WMLCardElement::findNamedCardInDocument(document, url.fragmentIdentifier())) { + if (card->isNewContext()) + pageState->reset(); + } + } + + // Prepare loading the destination url + ResourceRequest request(url); + + if (getAttribute(sendrefererAttr) == "true") + request.setHTTPReferrer(loader->outgoingReferrer()); + + String cacheControl = getAttribute(cache_controlAttr); + + if (m_formAttributes.method() == FormSubmission::PostMethod) + preparePOSTRequest(request, inSameDeck, cacheControl); + else + prepareGETRequest(request, url); + + // Set HTTP cache-control header if needed + if (!cacheControl.isEmpty()) { + request.setHTTPHeaderField("cache-control", cacheControl); + + if (cacheControl == "no-cache") + request.setCachePolicy(ReloadIgnoringCacheData); + } + + loader->load(request, false); +} + +void WMLGoElement::preparePOSTRequest(ResourceRequest& request, bool inSameDeck, const String& cacheControl) +{ + request.setHTTPMethod("POST"); + + if (inSameDeck && cacheControl != "no-cache") { + request.setCachePolicy(ReturnCacheDataDontLoad); + return; + } + + RefPtr<FormData> data; + + if (m_formAttributes.isMultiPartForm()) { // multipart/form-data + Vector<char> boundary = FormDataBuilder::generateUniqueBoundaryString(); + data = createFormData(boundary.data()); + request.setHTTPContentType(m_formAttributes.encodingType() + "; boundary=" + boundary.data()); + } else { + // text/plain or application/x-www-form-urlencoded + data = createFormData(CString()); + request.setHTTPContentType(m_formAttributes.encodingType()); + } + + request.setHTTPBody(data.get()); +} + +void WMLGoElement::prepareGETRequest(ResourceRequest& request, const KURL& url) +{ + request.setHTTPMethod("GET"); + + // Eventually display error message? + if (m_formAttributes.isMultiPartForm()) + return; + + RefPtr<FormData> data = createFormData(CString()); + + KURL remoteURL(url); + remoteURL.setQuery(data->flattenToString()); + request.setURL(remoteURL); +} + +PassRefPtr<FormData> WMLGoElement::createFormData(const CString& boundary) +{ + CString key; + CString value; + + Vector<char> encodedData; + TextEncoding encoding = FormDataBuilder::encodingFromAcceptCharset(m_formAttributes.acceptCharset(), document()).encodingForFormSubmission(); + + Vector<WMLPostfieldElement*>::iterator it = m_postfieldElements.begin(); + Vector<WMLPostfieldElement*>::iterator end = m_postfieldElements.end(); + + RefPtr<FormData> result = FormData::create(); + for (; it != end; ++it) { + (*it)->encodeData(encoding, key, value); + + if (m_formAttributes.isMultiPartForm()) { + Vector<char> header; + FormDataBuilder::beginMultiPartHeader(header, boundary, key); + FormDataBuilder::finishMultiPartHeader(header); + result->appendData(header.data(), header.size()); + + if (size_t dataSize = value.length()) + result->appendData(value.data(), dataSize); + + result->appendData("\r\n", 2); + } else + FormDataBuilder::addKeyValuePairAsFormData(encodedData, key, value); + } + + if (m_formAttributes.isMultiPartForm()) + FormDataBuilder::addBoundaryToMultiPartHeader(encodedData, boundary, true); + + result->appendData(encodedData.data(), encodedData.size()); + return result; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLGoElement.h b/Source/WebCore/wml/WMLGoElement.h new file mode 100644 index 0000000..d29e124 --- /dev/null +++ b/Source/WebCore/wml/WMLGoElement.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLGoElement_h +#define WMLGoElement_h + +#if ENABLE(WML) +#include "FormSubmission.h" +#include "WMLTaskElement.h" + +namespace WebCore { + +class FormData; +class ResourceRequest; +class WMLPostfieldElement; + +class WMLGoElement : public WMLTaskElement { +public: + static PassRefPtr<WMLGoElement> create(const QualifiedName&, Document*); + + WMLGoElement(const QualifiedName& tagName, Document*); + + void registerPostfieldElement(WMLPostfieldElement*); + void deregisterPostfieldElement(WMLPostfieldElement*); + + virtual void parseMappedAttribute(Attribute*); + virtual void executeTask(); + +private: + void preparePOSTRequest(ResourceRequest&, bool inSameDeck, const String& cacheControl); + void prepareGETRequest(ResourceRequest&, const KURL&); + + PassRefPtr<FormData> createFormData(const CString& boundary); + + Vector<WMLPostfieldElement*> m_postfieldElements; + FormSubmission::Attributes m_formAttributes; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLImageElement.cpp b/Source/WebCore/wml/WMLImageElement.cpp new file mode 100644 index 0000000..5e15ccb --- /dev/null +++ b/Source/WebCore/wml/WMLImageElement.cpp @@ -0,0 +1,156 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLImageElement.h" + +#include "Attribute.h" +#include "CSSPropertyNames.h" +#include "CSSValueKeywords.h" +#include "HTMLElement.h" +#include "HTMLNames.h" +#include "RenderImage.h" +#include "WMLNames.h" +#include "WMLVariables.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLImageElement::WMLImageElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) + , m_imageLoader(this) + , m_useFallbackAttribute(false) +{ +} + +PassRefPtr<WMLImageElement> WMLImageElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLImageElement(tagName, document)); +} + +WMLImageElement::~WMLImageElement() +{ +} + +bool WMLImageElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const +{ + if (attrName == HTMLNames::widthAttr || + attrName == HTMLNames::heightAttr || + attrName == HTMLNames::vspaceAttr || + attrName == HTMLNames::hspaceAttr) { + result = eUniversal; + return false; + } + + if (attrName == HTMLNames::alignAttr) { + result = eReplaced; + return false; + } + + return WMLElement::mapToEntry(attrName, result); +} + +void WMLImageElement::parseMappedAttribute(Attribute* attr) +{ + const QualifiedName& attrName = attr->name(); + + if (attrName == HTMLNames::altAttr) { + if (renderer() && renderer()->isImage()) + toRenderImage(renderer())->updateAltText(); + } else if (attrName == HTMLNames::srcAttr || attrName == localsrcAttr) + m_imageLoader.updateFromElementIgnoringPreviousError(); + else if (attrName == HTMLNames::widthAttr) + addCSSLength(attr, CSSPropertyWidth, attr->value()); + else if (attrName == HTMLNames::heightAttr) + addCSSLength(attr, CSSPropertyHeight, attr->value()); + else if (attrName == HTMLNames::vspaceAttr) { + addCSSLength(attr, CSSPropertyMarginTop, attr->value()); + addCSSLength(attr, CSSPropertyMarginBottom, attr->value()); + } else if (attrName == HTMLNames::hspaceAttr) { + addCSSLength(attr, CSSPropertyMarginLeft, attr->value()); + addCSSLength(attr, CSSPropertyMarginRight, attr->value()); + } else if (attrName == HTMLNames::alignAttr) + HTMLElement::addHTMLAlignmentToStyledElement(this, attr); + else + WMLElement::parseMappedAttribute(attr); +} + +void WMLImageElement::attach() +{ + WMLElement::attach(); + + if (renderer() && renderer()->isImage() && m_imageLoader.haveFiredBeforeLoadEvent()) { + RenderImage* imageObj = toRenderImage(renderer()); + RenderImageResource* renderImageResource = imageObj->imageResource(); + if (renderImageResource->hasImage()) + return; + renderImageResource->setCachedImage(m_imageLoader.image()); + + // If we have no image at all because we have no src attribute, set + // image height and width for the alt text instead. + if (!m_imageLoader.image() && !imageObj->cachedImage()) + imageObj->setImageSizeForAltText(); + } +} + +RenderObject* WMLImageElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + RenderImage* image = new (arena) RenderImage(this); + image->setImageResource(RenderImageResource::create()); + return image; +} + +void WMLImageElement::insertedIntoDocument() +{ + // If we have been inserted from a renderer-less document, + // our loader may have not fetched the image, so do it now. + if (!m_imageLoader.image()) + m_imageLoader.updateFromElement(); + + WMLElement::insertedIntoDocument(); +} + +bool WMLImageElement::isURLAttribute(Attribute* attr) const +{ + return attr->name() == HTMLNames::srcAttr + || attr->name() == localsrcAttr; +} + +const QualifiedName& WMLImageElement::imageSourceAttributeName() const +{ + // Spec: Any 'localsrc' parameter specified takes precedence over the + // image specified in the src parameter. + if (hasAttribute(localsrcAttr) && !m_useFallbackAttribute) + return localsrcAttr; + + return HTMLNames::srcAttr; +} + +String WMLImageElement::altText() const +{ + return substituteVariableReferences(getAttribute(HTMLNames::altAttr), document()); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLImageElement.h b/Source/WebCore/wml/WMLImageElement.h new file mode 100644 index 0000000..6421f6e --- /dev/null +++ b/Source/WebCore/wml/WMLImageElement.h @@ -0,0 +1,60 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLImageElement_h +#define WMLImageElement_h + +#if ENABLE(WML) +#include "WMLElement.h" +#include "WMLImageLoader.h" + +namespace WebCore { + +class WMLImageElement : public WMLElement { +public: + static PassRefPtr<WMLImageElement> create(const QualifiedName&, Document*); + + WMLImageElement(const QualifiedName& tagName, Document*); + virtual ~WMLImageElement(); + + virtual bool mapToEntry(const QualifiedName&, MappedAttributeEntry&) const; + virtual void parseMappedAttribute(Attribute*); + + virtual void attach(); + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + + virtual void insertedIntoDocument(); + virtual bool isURLAttribute(Attribute*) const; + virtual const QualifiedName& imageSourceAttributeName() const; + + String altText() const; + + bool useFallbackAttribute() { return m_useFallbackAttribute; } + void setUseFallbackAttribute(bool value) { m_useFallbackAttribute = value; } + +private: + WMLImageLoader m_imageLoader; + bool m_useFallbackAttribute; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLImageLoader.cpp b/Source/WebCore/wml/WMLImageLoader.cpp new file mode 100644 index 0000000..1e4c96b --- /dev/null +++ b/Source/WebCore/wml/WMLImageLoader.cpp @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLImageLoader.h" + +#include "CachedImage.h" +#include "HTMLNames.h" +#include "HTMLParserIdioms.h" +#include "WMLImageElement.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLImageLoader::WMLImageLoader(WMLImageElement* element) + : ImageLoader(element) +{ +} + +WMLImageLoader::~WMLImageLoader() +{ +} + +void WMLImageLoader::dispatchLoadEvent() +{ + // WML doesn't fire any events. +} + +String WMLImageLoader::sourceURI(const AtomicString& attr) const +{ + return KURL(element()->baseURI(), stripLeadingAndTrailingHTMLSpaces(attr)); +} + +void WMLImageLoader::notifyFinished(CachedResource* image) +{ + ImageLoader::notifyFinished(image); + + if (!image->errorOccurred()) + return; + + WMLImageElement* imageElement = static_cast<WMLImageElement*>(element()); + ASSERT(imageElement); + + // Loading both 'localsrc' and 'src' failed. Ignore this image. + if (imageElement->useFallbackAttribute()) + return; + + if (!imageElement->hasAttribute(localsrcAttr) && !imageElement->hasAttribute(HTMLNames::srcAttr)) + return; + + imageElement->setUseFallbackAttribute(true); + updateFromElementIgnoringPreviousError(); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLImageLoader.h b/Source/WebCore/wml/WMLImageLoader.h new file mode 100644 index 0000000..ecdb65a --- /dev/null +++ b/Source/WebCore/wml/WMLImageLoader.h @@ -0,0 +1,45 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLImageLoader_h +#define WMLImageLoader_h + +#if ENABLE(WML) +#include "ImageLoader.h" + +namespace WebCore { + +class WMLImageElement; + +class WMLImageLoader : public ImageLoader { +public: + WMLImageLoader(WMLImageElement*); + virtual ~WMLImageLoader(); + + virtual void dispatchLoadEvent(); + virtual String sourceURI(const AtomicString&) const; + + virtual void notifyFinished(CachedResource*); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLInputElement.cpp b/Source/WebCore/wml/WMLInputElement.cpp new file mode 100644 index 0000000..2d7310a --- /dev/null +++ b/Source/WebCore/wml/WMLInputElement.cpp @@ -0,0 +1,518 @@ +/** + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLInputElement.h" + +#include "Attribute.h" +#include "EventNames.h" +#include "FormDataList.h" +#include "Frame.h" +#include "HTMLNames.h" +#include "KeyboardEvent.h" +#include "RenderTextControlSingleLine.h" +#include "TextEvent.h" +#include "WMLDocument.h" +#include "WMLNames.h" +#include "WMLPageState.h" + +namespace WebCore { + +WMLInputElement::WMLInputElement(const QualifiedName& tagName, Document* doc) + : WMLFormControlElement(tagName, doc) + , m_isPasswordField(false) + , m_isEmptyOk(false) + , m_numOfCharsAllowedByMask(0) +{ +} + +PassRefPtr<WMLInputElement> WMLInputElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLInputElement(tagName, document)); +} + +WMLInputElement::~WMLInputElement() +{ + if (m_isPasswordField) + document()->unregisterForDocumentActivationCallbacks(this); +} + +static const AtomicString& formatCodes() +{ + DEFINE_STATIC_LOCAL(AtomicString, codes, ("AaNnXxMm")); + return codes; +} + +bool WMLInputElement::isKeyboardFocusable(KeyboardEvent*) const +{ + return WMLFormControlElement::isFocusable(); +} + +bool WMLInputElement::isMouseFocusable() const +{ + return WMLFormControlElement::isFocusable(); +} + +void WMLInputElement::dispatchFocusEvent() +{ + InputElement::dispatchFocusEvent(this, this); + WMLElement::dispatchFocusEvent(); +} + +void WMLInputElement::dispatchBlurEvent() +{ + // Firstly check if it is allowed to leave this input field + String val = value(); + if ((!m_isEmptyOk && val.isEmpty()) || !isConformedToInputMask(val)) { + updateFocusAppearance(true); + return; + } + + // update the name variable of WML input elmenet + String nameVariable = formControlName(); + if (!nameVariable.isEmpty()) + wmlPageStateForDocument(document())->storeVariable(nameVariable, val); + + InputElement::dispatchBlurEvent(this, this); + WMLElement::dispatchBlurEvent(); +} + +void WMLInputElement::updateFocusAppearance(bool restorePreviousSelection) +{ + InputElement::updateFocusAppearance(m_data, this, this, restorePreviousSelection); +} + +void WMLInputElement::aboutToUnload() +{ + InputElement::aboutToUnload(this, this); +} + +int WMLInputElement::size() const +{ + return m_data.size(); +} + +const AtomicString& WMLInputElement::formControlType() const +{ + // needs to be lowercase according to DOM spec + if (m_isPasswordField) { + DEFINE_STATIC_LOCAL(const AtomicString, password, ("password")); + return password; + } + + DEFINE_STATIC_LOCAL(const AtomicString, text, ("text")); + return text; +} + +const AtomicString& WMLInputElement::formControlName() const +{ + return m_data.name(); +} + +const String& WMLInputElement::suggestedValue() const +{ + return m_data.suggestedValue(); +} + +String WMLInputElement::value() const +{ + String value = m_data.value(); + if (value.isNull()) + value = constrainValue(getAttribute(HTMLNames::valueAttr)); + + return value; +} + +void WMLInputElement::setValue(const String& value, bool sendChangeEvent) +{ + setFormControlValueMatchesRenderer(false); + m_data.setValue(constrainValue(value)); + if (inDocument()) + document()->updateStyleIfNeeded(); + if (renderer()) + renderer()->updateFromElement(); + setNeedsStyleRecalc(); + + unsigned max = m_data.value().length(); + if (document()->focusedNode() == this) + InputElement::updateSelectionRange(this, this, max, max); + else + cacheSelection(max, max); + + InputElement::notifyFormStateChanged(this); +} + +void WMLInputElement::setValueForUser(const String& value) +{ + /* InputElement class defines pure virtual function 'setValueForUser', which + will be useful only in HTMLInputElement. Do nothing in 'WMLInputElement'. + */ +} + +void WMLInputElement::setValueFromRenderer(const String& value) +{ + InputElement::setValueFromRenderer(m_data, this, this, value); +} + +bool WMLInputElement::saveFormControlState(String& result) const +{ + if (m_isPasswordField) + return false; + + result = value(); + return true; +} + +void WMLInputElement::restoreFormControlState(const String& state) +{ + ASSERT(!m_isPasswordField); // should never save/restore password fields + setValue(state); +} + +void WMLInputElement::select() +{ + if (RenderTextControl* r = toRenderTextControl(renderer())) + setSelectionRange(this, 0, r->text().length()); +} + +void WMLInputElement::accessKeyAction(bool) +{ + // should never restore previous selection here + focus(false); +} + +void WMLInputElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::nameAttr) + m_data.setName(parseValueForbiddingVariableReferences(attr->value())); + else if (attr->name() == HTMLNames::typeAttr) { + String type = parseValueForbiddingVariableReferences(attr->value()); + m_isPasswordField = (type == "password"); + } else if (attr->name() == HTMLNames::valueAttr) { + // We only need to setChanged if the form is looking at the default value right now. + if (m_data.value().isNull()) + setNeedsStyleRecalc(); + setFormControlValueMatchesRenderer(false); + } else if (attr->name() == HTMLNames::maxlengthAttr) + InputElement::parseMaxLengthAttribute(m_data, this, this, attr); + else if (attr->name() == HTMLNames::sizeAttr) + InputElement::parseSizeAttribute(m_data, this, attr); + else if (attr->name() == WMLNames::formatAttr) + m_formatMask = validateInputMask(parseValueForbiddingVariableReferences(attr->value())); + else if (attr->name() == WMLNames::emptyokAttr) + m_isEmptyOk = (attr->value() == "true"); + else + WMLElement::parseMappedAttribute(attr); + + // FIXME: Handle 'accesskey' attribute + // FIXME: Handle 'tabindex' attribute + // FIXME: Handle 'title' attribute +} + +void WMLInputElement::copyNonAttributeProperties(const Element* source) +{ + const WMLInputElement* sourceElement = static_cast<const WMLInputElement*>(source); + m_data.setValue(sourceElement->m_data.value()); + WMLElement::copyNonAttributeProperties(source); +} + +RenderObject* WMLInputElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + return new (arena) RenderTextControlSingleLine(this, false); +} + +void WMLInputElement::detach() +{ + WMLElement::detach(); + setFormControlValueMatchesRenderer(false); +} + +bool WMLInputElement::appendFormData(FormDataList& encoding, bool) +{ + if (formControlName().isEmpty()) + return false; + + encoding.appendData(formControlName(), value()); + return true; +} + +void WMLInputElement::reset() +{ + setValue(String()); +} + +void WMLInputElement::defaultEventHandler(Event* evt) +{ + bool clickDefaultFormButton = false; + + if (evt->type() == eventNames().textInputEvent && evt->isTextEvent()) { + TextEvent* textEvent = static_cast<TextEvent*>(evt); + if (textEvent->data() == "\n") + clickDefaultFormButton = true; + else if (renderer() && !isConformedToInputMask(textEvent->data()[0], toRenderTextControl(renderer())->text().length() + 1)) + // If the inputed char doesn't conform to the input mask, stop handling + return; + } + + if (evt->type() == eventNames().keydownEvent && evt->isKeyboardEvent() && focused() && document()->frame() + && document()->frame()->editor()->doTextFieldCommandFromEvent(this, static_cast<KeyboardEvent*>(evt))) { + evt->setDefaultHandled(); + return; + } + + // Let the key handling done in EventTargetNode take precedence over the event handling here for editable text fields + if (!clickDefaultFormButton) { + WMLElement::defaultEventHandler(evt); + if (evt->defaultHandled()) + return; + } + + // Use key press event here since sending simulated mouse events + // on key down blocks the proper sending of the key press event. + if (evt->type() == eventNames().keypressEvent && evt->isKeyboardEvent()) { + // Simulate mouse click on the default form button for enter for these types of elements. + if (static_cast<KeyboardEvent*>(evt)->charCode() == '\r') + clickDefaultFormButton = true; + } + + if (clickDefaultFormButton) { + // Fire onChange for text fields. + RenderObject* r = renderer(); + if (r && toRenderTextControl(r)->wasChangedSinceLastChangeEvent()) { + dispatchEvent(Event::create(eventNames().changeEvent, true, false)); + + // Refetch the renderer since arbitrary JS code run during onchange can do anything, including destroying it. + r = renderer(); + if (r) + toRenderTextControl(r)->setChangedSinceLastChangeEvent(false); + } + + evt->setDefaultHandled(); + return; + } + + if (evt->isBeforeTextInsertedEvent()) + InputElement::handleBeforeTextInsertedEvent(m_data, this, this, evt); + + if (renderer() && (evt->isMouseEvent() || evt->isDragEvent() || evt->isWheelEvent() || evt->type() == eventNames().blurEvent || evt->type() == eventNames().focusEvent)) + toRenderTextControlSingleLine(renderer())->forwardEvent(evt); +} + +void WMLInputElement::cacheSelection(int start, int end) +{ + m_data.setCachedSelectionStart(start); + m_data.setCachedSelectionEnd(end); +} + +String WMLInputElement::constrainValue(const String& proposedValue) const +{ + return InputElement::sanitizeUserInputValue(this, proposedValue, m_data.maxLength()); +} + +void WMLInputElement::documentDidBecomeActive() +{ + ASSERT(m_isPasswordField); + reset(); +} + +void WMLInputElement::willMoveToNewOwnerDocument() +{ + // Always unregister for cache callbacks when leaving a document, even if we would otherwise like to be registered + if (m_isPasswordField) + document()->unregisterForDocumentActivationCallbacks(this); + + WMLElement::willMoveToNewOwnerDocument(); +} + +void WMLInputElement::didMoveToNewOwnerDocument() +{ + if (m_isPasswordField) + document()->registerForDocumentActivationCallbacks(this); + + WMLElement::didMoveToNewOwnerDocument(); +} + +void WMLInputElement::initialize() +{ + String nameVariable = formControlName(); + String variableValue; + WMLPageState* pageSate = wmlPageStateForDocument(document()); + ASSERT(pageSate); + if (!nameVariable.isEmpty()) + variableValue = pageSate->getVariable(nameVariable); + + if (variableValue.isEmpty() || !isConformedToInputMask(variableValue)) { + String val = value(); + if (isConformedToInputMask(val)) + variableValue = val; + else + variableValue = ""; + + pageSate->storeVariable(nameVariable, variableValue); + } + setValue(variableValue); + + if (!hasAttribute(WMLNames::emptyokAttr)) { + if (m_formatMask.isEmpty() || + // check if the format codes is just "*f" + (m_formatMask.length() == 2 && m_formatMask[0] == '*' && formatCodes().find(m_formatMask[1]) != -1)) + m_isEmptyOk = true; + } +} + +String WMLInputElement::validateInputMask(const String& inputMask) +{ + bool isValid = true; + bool hasWildcard = false; + unsigned escapeCharCount = 0; + unsigned maskLength = inputMask.length(); + UChar formatCode; + + for (unsigned i = 0; i < maskLength; ++i) { + formatCode = inputMask[i]; + if (formatCodes().find(formatCode) == -1) { + if (formatCode == '*' || (WTF::isASCIIDigit(formatCode) && formatCode != '0')) { + // validate codes which ends with '*f' or 'nf' + formatCode = inputMask[++i]; + if ((i + 1 != maskLength) || formatCodes().find(formatCode) == -1) { + isValid = false; + break; + } + hasWildcard = true; + } else if (formatCode == '\\') { + //skip over the next mask character + ++i; + ++escapeCharCount; + } else { + isValid = false; + break; + } + } + } + + if (!isValid) + return String(); + + // calculate the number of characters allowed to be entered by input mask + m_numOfCharsAllowedByMask = maskLength; + + if (escapeCharCount) + m_numOfCharsAllowedByMask -= escapeCharCount; + + if (hasWildcard) { + formatCode = inputMask[maskLength - 2]; + if (formatCode == '*') + m_numOfCharsAllowedByMask = m_data.maxLength(); + else { + unsigned leftLen = String(&formatCode).toInt(); + m_numOfCharsAllowedByMask = leftLen + m_numOfCharsAllowedByMask - 2; + } + } + + return inputMask; +} + +bool WMLInputElement::isConformedToInputMask(const String& inputChars) +{ + for (unsigned i = 0; i < inputChars.length(); ++i) + if (!isConformedToInputMask(inputChars[i], i + 1, false)) + return false; + + return true; +} + +bool WMLInputElement::isConformedToInputMask(UChar inChar, unsigned inputCharCount, bool isUserInput) +{ + if (m_formatMask.isEmpty()) + return true; + + if (inputCharCount > m_numOfCharsAllowedByMask) + return false; + + unsigned maskIndex = 0; + if (isUserInput) { + unsigned cursorPosition = 0; + if (renderer()) + cursorPosition = toRenderTextControl(renderer())->selectionStart(); + else + cursorPosition = m_data.cachedSelectionStart(); + + maskIndex = cursorPositionToMaskIndex(cursorPosition); + } else + maskIndex = cursorPositionToMaskIndex(inputCharCount - 1); + + bool ok = true; + UChar mask = m_formatMask[maskIndex]; + // match the inputed character with input mask + switch (mask) { + case 'A': + ok = !WTF::isASCIIDigit(inChar) && !WTF::isASCIILower(inChar) && WTF::isASCIIPrintable(inChar); + break; + case 'a': + ok = !WTF::isASCIIDigit(inChar) && !WTF::isASCIIUpper(inChar) && WTF::isASCIIPrintable(inChar); + break; + case 'N': + ok = WTF::isASCIIDigit(inChar); + break; + case 'n': + ok = !WTF::isASCIIAlpha(inChar) && WTF::isASCIIPrintable(inChar); + break; + case 'X': + ok = !WTF::isASCIILower(inChar) && WTF::isASCIIPrintable(inChar); + break; + case 'x': + ok = !WTF::isASCIIUpper(inChar) && WTF::isASCIIPrintable(inChar); + break; + case 'M': + ok = WTF::isASCIIPrintable(inChar); + break; + case 'm': + ok = WTF::isASCIIPrintable(inChar); + break; + default: + ok = (mask == inChar); + break; + } + + return ok; +} + +unsigned WMLInputElement::cursorPositionToMaskIndex(unsigned cursorPosition) +{ + UChar mask; + int index = -1; + do { + mask = m_formatMask[++index]; + if (mask == '\\') + ++index; + else if (mask == '*' || (WTF::isASCIIDigit(mask) && mask != '0')) { + index = m_formatMask.length() - 1; + break; + } + } while (cursorPosition--); + + return index; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLInputElement.h b/Source/WebCore/wml/WMLInputElement.h new file mode 100644 index 0000000..df7f497 --- /dev/null +++ b/Source/WebCore/wml/WMLInputElement.h @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLInputElement_h +#define WMLInputElement_h + +#if ENABLE(WML) +#include "WMLFormControlElement.h" +#include "InputElement.h" + +namespace WebCore { + +class FormDataList; + +class WMLInputElement : public WMLFormControlElement, public InputElement { +public: + static PassRefPtr<WMLInputElement> create(const QualifiedName&, Document*); + + WMLInputElement(const QualifiedName& tagName, Document*); + virtual ~WMLInputElement(); + + virtual bool isKeyboardFocusable(KeyboardEvent*) const; + virtual bool isMouseFocusable() const; + virtual void dispatchFocusEvent(); + virtual void dispatchBlurEvent(); + virtual void updateFocusAppearance(bool restorePreviousSelection); + virtual void aboutToUnload(); + + virtual bool shouldUseInputMethod() const { return !m_isPasswordField; } + virtual bool isChecked() const { return false; } + virtual bool isAutofilled() const { return false; } + virtual bool isIndeterminate() const { return false; } + virtual bool isTextFormControl() const { return true; } + virtual bool isRadioButton() const { return false; } + virtual bool isCheckbox() const { return false; } + virtual bool isTextField() const { return true; } + virtual bool isSearchField() const { return false; } + virtual bool isInputTypeHidden() const { return false; } + virtual bool isPasswordField() const { return m_isPasswordField; } + virtual bool searchEventsShouldBeDispatched() const { return false; } + + virtual int size() const; + virtual const AtomicString& formControlType() const; + virtual const AtomicString& formControlName() const; + virtual const String& suggestedValue() const; + virtual String value() const; + virtual void setValue(const String&, bool sendChangeEvent = false); + virtual void setValueForUser(const String&); + virtual void setValueFromRenderer(const String&); + + virtual bool saveFormControlState(String& value) const; + virtual void restoreFormControlState(const String&); + + virtual void select(); + virtual void accessKeyAction(bool sendToAnyElement); + virtual void parseMappedAttribute(Attribute*); + + virtual void copyNonAttributeProperties(const Element* source); + + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual void detach(); + virtual bool appendFormData(FormDataList&, bool); + virtual void reset(); + + virtual void defaultEventHandler(Event*); + virtual void cacheSelection(int start, int end); + + virtual bool isAcceptableValue(const String&) const { return true; } + virtual String sanitizeValue(const String& proposedValue) const { return constrainValue(proposedValue); } + + virtual void documentDidBecomeActive(); + + virtual void willMoveToNewOwnerDocument(); + virtual void didMoveToNewOwnerDocument(); + + bool isConformedToInputMask(const String&); + bool isConformedToInputMask(UChar, unsigned, bool isUserInput = true); +#if ENABLE(WCSS) + virtual InputElementData data() const { return m_data; } +#endif + +private: + friend class WMLCardElement; + void initialize(); + + virtual bool supportsMaxLength() const { return true; } + String validateInputMask(const String&); + unsigned cursorPositionToMaskIndex(unsigned); + String constrainValue(const String&) const; + + InputElementData m_data; + bool m_isPasswordField; + bool m_isEmptyOk; + String m_formatMask; + unsigned m_numOfCharsAllowedByMask; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLInsertedLegendElement.cpp b/Source/WebCore/wml/WMLInsertedLegendElement.cpp new file mode 100644 index 0000000..0a18b4a --- /dev/null +++ b/Source/WebCore/wml/WMLInsertedLegendElement.cpp @@ -0,0 +1,44 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLInsertedLegendElement.h" + +namespace WebCore { + +WMLInsertedLegendElement::WMLInsertedLegendElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLInsertedLegendElement> WMLInsertedLegendElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLInsertedLegendElement(tagName, document)); +} + +WMLInsertedLegendElement::~WMLInsertedLegendElement() +{ +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLInsertedLegendElement.h b/Source/WebCore/wml/WMLInsertedLegendElement.h new file mode 100644 index 0000000..e79550e --- /dev/null +++ b/Source/WebCore/wml/WMLInsertedLegendElement.h @@ -0,0 +1,40 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLInsertedLegendElement_h +#define WMLInsertedLegendElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLInsertedLegendElement : public WMLElement { +public: + static PassRefPtr<WMLInsertedLegendElement> create(const QualifiedName&, Document*); + + WMLInsertedLegendElement(const QualifiedName& tagName, Document*); + virtual ~WMLInsertedLegendElement(); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLIntrinsicEvent.cpp b/Source/WebCore/wml/WMLIntrinsicEvent.cpp new file mode 100644 index 0000000..bb631b9 --- /dev/null +++ b/Source/WebCore/wml/WMLIntrinsicEvent.cpp @@ -0,0 +1,53 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLIntrinsicEvent.h" + +#include "HTMLNames.h" +#include "WMLElementFactory.h" +#include "WMLNames.h" +#include "WMLTaskElement.h" + +namespace WebCore { + +using namespace WMLNames; + +static PassRefPtr<WMLTaskElement> createTaskElement(Document* document) +{ + return static_pointer_cast<WMLTaskElement>(WMLElementFactory::createWMLElement(goTag, document, false)); +} + +WMLIntrinsicEvent::WMLIntrinsicEvent(Document* document, const String& targetURL) + : m_taskElement(createTaskElement(document)) +{ + m_taskElement->setAttribute(HTMLNames::hrefAttr, targetURL); +} + +WMLIntrinsicEvent::WMLIntrinsicEvent(WMLTaskElement* taskElement) + : m_taskElement(taskElement) +{ +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLIntrinsicEvent.h b/Source/WebCore/wml/WMLIntrinsicEvent.h new file mode 100644 index 0000000..9a974fb --- /dev/null +++ b/Source/WebCore/wml/WMLIntrinsicEvent.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLIntrinsicEvent_h +#define WMLIntrinsicEvent_h + +#if ENABLE(WML) +#include "WMLTaskElement.h" + +#include <wtf/PassRefPtr.h> +#include <wtf/RefCounted.h> +#include <wtf/RefPtr.h> + +namespace WebCore { + +class Document; + +class WMLIntrinsicEvent : public RefCounted<WMLIntrinsicEvent> { +public: + static PassRefPtr<WMLIntrinsicEvent> create(Document* document, const String& targetURL) + { + return adoptRef(new WMLIntrinsicEvent(document, targetURL)); + } + + static PassRefPtr<WMLIntrinsicEvent> createWithTask(WMLTaskElement* taskElement) + { + return adoptRef(new WMLIntrinsicEvent(taskElement)); + } + + WMLTaskElement* taskElement() const { return m_taskElement.get(); } + +private: + WMLIntrinsicEvent(Document*, const String& targetURL); + WMLIntrinsicEvent(WMLTaskElement*); + + RefPtr<WMLTaskElement> m_taskElement; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLIntrinsicEventHandler.cpp b/Source/WebCore/wml/WMLIntrinsicEventHandler.cpp new file mode 100644 index 0000000..8e4c276 --- /dev/null +++ b/Source/WebCore/wml/WMLIntrinsicEventHandler.cpp @@ -0,0 +1,61 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLIntrinsicEventHandler.h" + +namespace WebCore { + +WMLIntrinsicEventHandler::WMLIntrinsicEventHandler() +{ +} + +bool WMLIntrinsicEventHandler::registerIntrinsicEvent(WMLIntrinsicEventType type, PassRefPtr<WMLIntrinsicEvent> event) +{ + if (m_events.contains(type)) + return false; + + m_events.set(type, event); + return true; +} + +void WMLIntrinsicEventHandler::deregisterIntrinsicEvent(WMLIntrinsicEventType type) +{ + if (m_events.contains(type)) + m_events.remove(type); +} + +void WMLIntrinsicEventHandler::triggerIntrinsicEvent(WMLIntrinsicEventType type) const +{ + RefPtr<WMLIntrinsicEvent> event = m_events.get(type); + ASSERT(event->taskElement()); + event->taskElement()->executeTask(); +} + +bool WMLIntrinsicEventHandler::hasIntrinsicEvent(WMLIntrinsicEventType type) const +{ + return m_events.contains(type); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLIntrinsicEventHandler.h b/Source/WebCore/wml/WMLIntrinsicEventHandler.h new file mode 100644 index 0000000..8ac6d1b --- /dev/null +++ b/Source/WebCore/wml/WMLIntrinsicEventHandler.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLIntrinsicEventHandler_h +#define WMLIntrinsicEventHandler_h + +#if ENABLE(WML) +#include <wtf/HashMap.h> +#include <wtf/PassRefPtr.h> + +#include "WMLIntrinsicEvent.h" + +namespace WebCore { + +enum WMLIntrinsicEventType { + WMLIntrinsicEventUnknown = 0, + WMLIntrinsicEventOnEnterForward, + WMLIntrinsicEventOnEnterBackward, + WMLIntrinsicEventOnTimer, + WMLIntrinsicEventOnPick +}; + +class WMLIntrinsicEvent; + +class WMLIntrinsicEventHandler { +public: + WMLIntrinsicEventHandler(); + + bool registerIntrinsicEvent(WMLIntrinsicEventType, PassRefPtr<WMLIntrinsicEvent>); + void deregisterIntrinsicEvent(WMLIntrinsicEventType); + void triggerIntrinsicEvent(WMLIntrinsicEventType) const; + bool hasIntrinsicEvent(WMLIntrinsicEventType) const; + +private: + typedef HashMap<int, RefPtr<WMLIntrinsicEvent> > EventMap; + EventMap m_events; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLMetaElement.cpp b/Source/WebCore/wml/WMLMetaElement.cpp new file mode 100644 index 0000000..2b8e00d --- /dev/null +++ b/Source/WebCore/wml/WMLMetaElement.cpp @@ -0,0 +1,70 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLMetaElement.h" + +#include "Attribute.h" +#include "Document.h" +#include "HTMLNames.h" + +namespace WebCore { + +WMLMetaElement::WMLMetaElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLMetaElement> WMLMetaElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLMetaElement(tagName, document)); +} + +WMLMetaElement::~WMLMetaElement() +{ +} + +void WMLMetaElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::http_equivAttr) + m_equiv = parseValueForbiddingVariableReferences(attr->value()); + else if (attr->name() == HTMLNames::contentAttr) + m_content = parseValueForbiddingVariableReferences(attr->value()); + else if (attr->name() == HTMLNames::nameAttr) { + // FIXME: The user agent must ignore any meta-data named with this attribute. + } else + WMLElement::parseMappedAttribute(attr); +} + +void WMLMetaElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + if (m_equiv.isNull() || m_content.isNull()) + return; + + document()->processHttpEquiv(m_equiv, m_content); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLMetaElement.h b/Source/WebCore/wml/WMLMetaElement.h new file mode 100644 index 0000000..16e2268 --- /dev/null +++ b/Source/WebCore/wml/WMLMetaElement.h @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLMetaElement_h +#define WMLMetaElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLMetaElement : public WMLElement { +public: + static PassRefPtr<WMLMetaElement> create(const QualifiedName&, Document*); + + WMLMetaElement(const QualifiedName& tagName, Document*); + virtual ~WMLMetaElement(); + + virtual void parseMappedAttribute(Attribute*); + virtual void insertedIntoDocument(); + +private: + String m_equiv; + String m_content; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLNoopElement.cpp b/Source/WebCore/wml/WMLNoopElement.cpp new file mode 100644 index 0000000..fbd3788 --- /dev/null +++ b/Source/WebCore/wml/WMLNoopElement.cpp @@ -0,0 +1,71 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLNoopElement.h" + +#include "WMLDoElement.h" +#include "WMLErrorHandling.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLNoopElement::WMLNoopElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLNoopElement> WMLNoopElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLNoopElement(tagName, document)); +} + +WMLNoopElement::~WMLNoopElement() +{ +} + +void WMLNoopElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + ContainerNode* parent = parentNode(); + if (!parent || !parent->isWMLElement()) + return; + + if (parent->hasTagName(doTag)) { + WMLDoElement* doElement = static_cast<WMLDoElement*>(parent); + doElement->setNoop(true); + + if (doElement->attached()) + doElement->detach(); + + ASSERT(!doElement->attached()); + doElement->attach(); + } else if (parent->hasTagName(anchorTag)) + reportWMLError(document(), WMLErrorForbiddenTaskInAnchorElement); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLNoopElement.h b/Source/WebCore/wml/WMLNoopElement.h new file mode 100644 index 0000000..be0413c --- /dev/null +++ b/Source/WebCore/wml/WMLNoopElement.h @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLNoopElement_h +#define WMLNoopElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLNoopElement : public WMLElement { +public: + static PassRefPtr<WMLNoopElement> create(const QualifiedName&, Document*); + + WMLNoopElement(const QualifiedName& tagName, Document*); + virtual ~WMLNoopElement(); + + virtual void insertedIntoDocument(); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLOnEventElement.cpp b/Source/WebCore/wml/WMLOnEventElement.cpp new file mode 100644 index 0000000..ad6684b --- /dev/null +++ b/Source/WebCore/wml/WMLOnEventElement.cpp @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLOnEventElement.h" + +#include "Attribute.h" +#include "HTMLNames.h" +#include "WMLErrorHandling.h" +#include "WMLEventHandlingElement.h" +#include "WMLIntrinsicEventHandler.h" +#include "WMLNames.h" +#include "WMLVariables.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLOnEventElement::WMLOnEventElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) + , m_type(WMLIntrinsicEventUnknown) +{ +} + +PassRefPtr<WMLOnEventElement> WMLOnEventElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLOnEventElement(tagName, document)); +} + +void WMLOnEventElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::typeAttr) { + String parsedValue = parseValueForbiddingVariableReferences(attr->value()); + if (parsedValue.isEmpty()) + return; + + if (parsedValue == onenterforwardAttr) + m_type = WMLIntrinsicEventOnEnterForward; + else if (parsedValue == onenterbackwardAttr) + m_type = WMLIntrinsicEventOnEnterBackward; + else if (parsedValue == ontimerAttr) + m_type = WMLIntrinsicEventOnTimer; + else if (parsedValue == onpickAttr) + m_type = WMLIntrinsicEventOnPick; + } else + WMLElement::parseMappedAttribute(attr); +} + +static inline WMLEventHandlingElement* eventHandlingParent(Node* parent) +{ + if (!parent || !parent->isWMLElement()) + return 0; + + return toWMLEventHandlingElement(static_cast<WMLElement*>(parent)); +} + +void WMLOnEventElement::registerTask(WMLTaskElement* task) +{ + if (m_type == WMLIntrinsicEventUnknown) + return; + + // Register intrinsic event to the event handler of the owner of onevent element + WMLEventHandlingElement* eventHandlingElement = eventHandlingParent(parentNode()); + if (!eventHandlingElement) + return; + + eventHandlingElement->createEventHandlerIfNeeded(); + + RefPtr<WMLIntrinsicEvent> event = WMLIntrinsicEvent::createWithTask(task); + if (!eventHandlingElement->eventHandler()->registerIntrinsicEvent(m_type, event)) + reportWMLError(document(), WMLErrorConflictingEventBinding); +} + +void WMLOnEventElement::deregisterTask(WMLTaskElement*) +{ + WMLEventHandlingElement* eventHandlingElement = eventHandlingParent(parentNode()); + if (!eventHandlingElement) + return; + + eventHandlingElement->eventHandler()->deregisterIntrinsicEvent(m_type); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLOnEventElement.h b/Source/WebCore/wml/WMLOnEventElement.h new file mode 100644 index 0000000..8bbaa1d --- /dev/null +++ b/Source/WebCore/wml/WMLOnEventElement.h @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLOnEventElement_h +#define WMLOnEventElement_h + +#if ENABLE(WML) +#include "WMLElement.h" +#include "WMLIntrinsicEventHandler.h" + +namespace WebCore { + +class WMLTaskElement; + +class WMLOnEventElement : public WMLElement { +public: + static PassRefPtr<WMLOnEventElement> create(const QualifiedName&, Document*); + + WMLOnEventElement(const QualifiedName& tagName, Document*); + + virtual void parseMappedAttribute(Attribute*); + + void registerTask(WMLTaskElement*); + void deregisterTask(WMLTaskElement*); + +private: + WMLIntrinsicEventType m_type; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLOptGroupElement.cpp b/Source/WebCore/wml/WMLOptGroupElement.cpp new file mode 100644 index 0000000..3e15c7b --- /dev/null +++ b/Source/WebCore/wml/WMLOptGroupElement.cpp @@ -0,0 +1,135 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLOptGroupElement.h" + +#include "Attribute.h" +#include "Document.h" +#include "HTMLNames.h" +#include "NodeRenderStyle.h" +#include "RenderStyle.h" +#include "WMLNames.h" +#include "WMLSelectElement.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLOptGroupElement::WMLOptGroupElement(const QualifiedName& tagName, Document* doc) + : WMLFormControlElement(tagName, doc) +{ +} + +PassRefPtr<WMLOptGroupElement> WMLOptGroupElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLOptGroupElement(tagName, document)); +} + +WMLOptGroupElement::~WMLOptGroupElement() +{ +} + +const AtomicString& WMLOptGroupElement::formControlType() const +{ + DEFINE_STATIC_LOCAL(const AtomicString, optgroup, ("optgroup")); + return optgroup; +} + +static inline WMLSelectElement* ownerSelectElement(Element* element) +{ + ContainerNode* select = element->parentNode(); + while (select && !select->hasTagName(selectTag)) + select = select->parentNode(); + + if (!select) + return 0; + + return static_cast<WMLSelectElement*>(select); +} + +void WMLOptGroupElement::accessKeyAction(bool) +{ + WMLSelectElement* select = ownerSelectElement(this); + if (!select || select->focused()) + return; + + // send to the parent to bring focus to the list box + select->accessKeyAction(false); +} + +void WMLOptGroupElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) +{ + recalcSelectOptions(); + WMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); +} + +void WMLOptGroupElement::parseMappedAttribute(Attribute* attr) +{ + WMLFormControlElement::parseMappedAttribute(attr); + recalcSelectOptions(); +} + +void WMLOptGroupElement::attach() +{ + if (parentNode()->renderStyle()) + setRenderStyle(styleForRenderer()); + WMLFormControlElement::attach(); +} + +void WMLOptGroupElement::detach() +{ + m_style.clear(); + WMLFormControlElement::detach(); +} + +void WMLOptGroupElement::setRenderStyle(PassRefPtr<RenderStyle> style) +{ + m_style = style; +} + +RenderStyle* WMLOptGroupElement::nonRendererRenderStyle() const +{ + return m_style.get(); +} + +String WMLOptGroupElement::groupLabelText() const +{ + String itemText = document()->displayStringModifiedByEncoding(title()); + + // In WinIE, leading and trailing whitespace is ignored in options and optgroups. We match this behavior. + itemText = itemText.stripWhiteSpace(); + // We want to collapse our whitespace too. This will match other browsers. + itemText = itemText.simplifyWhiteSpace(); + + return itemText; +} + +void WMLOptGroupElement::recalcSelectOptions() +{ + if (WMLSelectElement* select = ownerSelectElement(this)) + select->setRecalcListItems(); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLOptGroupElement.h b/Source/WebCore/wml/WMLOptGroupElement.h new file mode 100644 index 0000000..c49749e --- /dev/null +++ b/Source/WebCore/wml/WMLOptGroupElement.h @@ -0,0 +1,62 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLOptGroupElement_h +#define WMLOptGroupElement_h + +#if ENABLE(WML) +#include "WMLFormControlElement.h" +#include "OptionGroupElement.h" + +namespace WebCore { + +class WMLOptGroupElement : public WMLFormControlElement, public OptionGroupElement { +public: + static PassRefPtr<WMLOptGroupElement> create(const QualifiedName&, Document*); + + WMLOptGroupElement(const QualifiedName& tagName, Document*); + virtual ~WMLOptGroupElement(); + + virtual const AtomicString& formControlType() const; + + virtual bool rendererIsNeeded(RenderStyle*) { return false; } + + virtual void accessKeyAction(bool sendToAnyElement); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void parseMappedAttribute(Attribute*); + + virtual void attach(); + virtual void detach(); + virtual void setRenderStyle(PassRefPtr<RenderStyle>); + + virtual String groupLabelText() const; + +private: + virtual RenderStyle* nonRendererRenderStyle() const; + void recalcSelectOptions(); + +private: + RefPtr<RenderStyle> m_style; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLOptionElement.cpp b/Source/WebCore/wml/WMLOptionElement.cpp new file mode 100644 index 0000000..6c8aa74 --- /dev/null +++ b/Source/WebCore/wml/WMLOptionElement.cpp @@ -0,0 +1,186 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLOptionElement.h" + +#include "Attribute.h" +#include "HTMLNames.h" +#include "NodeRenderStyle.h" +#include "RenderStyle.h" +#include "WMLNames.h" +#include "WMLSelectElement.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLOptionElement::WMLOptionElement(const QualifiedName& tagName, Document* doc) + : WMLFormControlElement(tagName, doc) +{ +} + +PassRefPtr<WMLOptionElement> WMLOptionElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLOptionElement(tagName, document)); +} + +WMLOptionElement::~WMLOptionElement() +{ +} + +const AtomicString& WMLOptionElement::formControlType() const +{ + DEFINE_STATIC_LOCAL(const AtomicString, option, ("option")); + return option; +} + +static inline WMLSelectElement* ownerSelectElement(Element* element) +{ + ContainerNode* select = element->parentNode(); + while (select && !select->hasTagName(selectTag)) + select = select->parentNode(); + + if (!select) + return 0; + + return static_cast<WMLSelectElement*>(select); +} + +void WMLOptionElement::accessKeyAction(bool) +{ + if (WMLSelectElement* select = ownerSelectElement(this)) + select->accessKeySetSelectedIndex(OptionElement::optionIndex(select, this)); +} + +void WMLOptionElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) +{ + if (WMLSelectElement* select = ownerSelectElement(this)) + select->childrenChanged(changedByParser); + + WMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); +} + +void WMLOptionElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::valueAttr) + m_data.setValue(parseValueSubstitutingVariableReferences(attr->value())); + else if (attr->name() == HTMLNames::titleAttr) + m_data.setLabel(parseValueSubstitutingVariableReferences(attr->value())); + else if (attr->name() == onpickAttr) { + // Register intrinsic event in card + RefPtr<WMLIntrinsicEvent> event = WMLIntrinsicEvent::create(document(), attr->value()); + + createEventHandlerIfNeeded(); + eventHandler()->registerIntrinsicEvent(WMLIntrinsicEventOnPick, event); + } else + WMLFormControlElement::parseMappedAttribute(attr); +} + +void WMLOptionElement::attach() +{ + if (parentNode()->renderStyle()) + setRenderStyle(styleForRenderer()); + WMLFormControlElement::attach(); +} + +void WMLOptionElement::detach() +{ + m_style.clear(); + WMLFormControlElement::detach(); +} + +void WMLOptionElement::setRenderStyle(PassRefPtr<RenderStyle> style) +{ + m_style = style; +} + +void WMLOptionElement::insertedIntoDocument() +{ + WMLSelectElement* select; + if (selected() && (select = ownerSelectElement(this))) + select->scrollToSelection(); + + WMLFormControlElement::insertedIntoDocument(); +} + +bool WMLOptionElement::selected() const +{ + return m_data.selected(); +} + +void WMLOptionElement::setSelectedState(bool selected) +{ + if (this->selected() == selected) + return; + + OptionElement::setSelectedState(m_data, this, selected); + + if (WMLSelectElement* select = ownerSelectElement(this)) { + if (select->multiple() || selected) + handleIntrinsicEventIfNeeded(); + } +} + +String WMLOptionElement::value() const +{ + return OptionElement::collectOptionValue(m_data, this); +} + +String WMLOptionElement::text() const +{ + return OptionElement::collectOptionLabelOrText(m_data, this); +} + +String WMLOptionElement::textIndentedToRespectGroupLabel() const +{ + return OptionElement::collectOptionTextRespectingGroupLabel(m_data, this); +} + +RenderStyle* WMLOptionElement::nonRendererRenderStyle() const +{ + return m_style.get(); +} + +void WMLOptionElement::handleIntrinsicEventIfNeeded() +{ + WMLSelectElement* select = ownerSelectElement(this); + if (!select || !select->initialized()) + return; + + WMLIntrinsicEventHandler* eventHandler = this->eventHandler(); + if (!eventHandler) + return; + + if (eventHandler->hasIntrinsicEvent(WMLIntrinsicEventOnPick)) + eventHandler->triggerIntrinsicEvent(WMLIntrinsicEventOnPick); +} + +bool WMLOptionElement::disabled() const +{ + /* Dummy implementation, as disabled() is pure virtual in OptionElement class */ + return false; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLOptionElement.h b/Source/WebCore/wml/WMLOptionElement.h new file mode 100644 index 0000000..41a4638 --- /dev/null +++ b/Source/WebCore/wml/WMLOptionElement.h @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLOptionElement_h +#define WMLOptionElement_h + +#if ENABLE(WML) +#include "OptionElement.h" +#include "WMLFormControlElement.h" +#include "WMLEventHandlingElement.h" + +namespace WebCore { + +class WMLOptionElement : public WMLFormControlElement, public WMLEventHandlingElement, public OptionElement { +public: + static PassRefPtr<WMLOptionElement> create(const QualifiedName&, Document*); + + WMLOptionElement(const QualifiedName& tagName, Document*); + virtual ~WMLOptionElement(); + + virtual const AtomicString& formControlType() const; + + virtual bool rendererIsNeeded(RenderStyle*) { return false; } + + virtual void accessKeyAction(bool sendToAnyElement); + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + virtual void parseMappedAttribute(Attribute*); + + virtual void attach(); + virtual void detach(); + virtual void setRenderStyle(PassRefPtr<RenderStyle>); + + virtual void insertedIntoDocument(); + + virtual bool selected() const; + virtual void setSelectedState(bool); + + virtual String text() const; + virtual String textIndentedToRespectGroupLabel() const; + virtual String value() const; + + virtual bool disabled() const; + +private: + virtual RenderStyle* nonRendererRenderStyle() const; + void handleIntrinsicEventIfNeeded(); + +private: + OptionElementData m_data; + RefPtr<RenderStyle> m_style; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLPElement.cpp b/Source/WebCore/wml/WMLPElement.cpp new file mode 100644 index 0000000..629b49f --- /dev/null +++ b/Source/WebCore/wml/WMLPElement.cpp @@ -0,0 +1,118 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLPElement.h" + +#include "Attribute.h" +#include "CSSPropertyNames.h" +#include "CSSValueKeywords.h" +#include "Document.h" +#include "HTMLNames.h" +#include "NodeList.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLPElement::WMLPElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLPElement> WMLPElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLPElement(tagName, document)); +} + +bool WMLPElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const +{ + if (attrName == HTMLNames::alignAttr) { + result = eBlock; // We can share with DIV here. + return false; + } + + return WMLElement::mapToEntry(attrName, result); +} + +void WMLPElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::alignAttr) { + const AtomicString& value = attr->value(); + if (equalIgnoringCase(value, "middle") || equalIgnoringCase(value, "center")) + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitCenter); + else if (equalIgnoringCase(value, "left")) + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitLeft); + else if (equalIgnoringCase(value, "right")) + addCSSProperty(attr, CSSPropertyTextAlign, CSSValueWebkitRight); + else + addCSSProperty(attr, CSSPropertyTextAlign, value); + } else if (attr->name() == modeAttr) { + m_mode = attr->value(); + if (m_mode == "wrap") + addCSSProperty(attr, CSSPropertyWordWrap, CSSValueBreakWord); + else if (m_mode == "nowrap") + addCSSProperty(attr, CSSPropertyWhiteSpace, CSSValueNowrap); + } else + WMLElement::parseMappedAttribute(attr); +} + +void WMLPElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + // If not explicitly specified, the linewrap mode is identical to + // the line-wrap mode of the previous paragraph in the text flow of + // a card. The default mode for the first paragraph in a card is wrap. + if (!m_mode.isEmpty()) + return; + + RefPtr<NodeList> nodeList = document()->getElementsByTagName("p"); + if (!nodeList) + return; + + unsigned length = nodeList->length(); + if (length < 2) + return; + + // Assure we're the last inserted paragraph element + // This only works while parsing, otherwhise this statement is never true. + if (nodeList->item(length - 1) != this) + return; + + WMLPElement* lastParagraph = static_cast<WMLPElement*>(nodeList->item(length - 2)); + ASSERT(lastParagraph); + + String lastMode = lastParagraph->getAttribute(modeAttr); + if (lastMode.isEmpty() || lastMode == "wrap") // Default value, do nothing. + return; + + setAttribute(modeAttr, lastMode); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLPElement.h b/Source/WebCore/wml/WMLPElement.h new file mode 100644 index 0000000..32a35b1 --- /dev/null +++ b/Source/WebCore/wml/WMLPElement.h @@ -0,0 +1,50 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Copyright (C) 1999 Lars Knoll (knoll@kde.org) + * (C) 1999 Antti Koivisto (koivisto@kde.org) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLPElement_h +#define WMLPElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLPElement : public WMLElement { +public: + static PassRefPtr<WMLPElement> create(const QualifiedName&, Document*); + + WMLPElement(const QualifiedName& tagName, Document*); + + virtual bool mapToEntry(const QualifiedName&, MappedAttributeEntry&) const; + virtual void parseMappedAttribute(Attribute*); + + virtual void insertedIntoDocument(); + +private: + String m_mode; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLPageState.cpp b/Source/WebCore/wml/WMLPageState.cpp new file mode 100644 index 0000000..a3c6243 --- /dev/null +++ b/Source/WebCore/wml/WMLPageState.cpp @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * Copyright (C) 2004-2007 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLPageState.h" + +#include "BackForwardController.h" +#include "BackForwardList.h" +#include "Document.h" +#include "Frame.h" +#include "HistoryItem.h" +#include "KURL.h" +#include "Page.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +WMLPageState::WMLPageState(Page* page) + : m_page(page) + , m_hasAccessControlData(false) +{ +} + +WMLPageState::~WMLPageState() +{ + m_variables.clear(); +} + +#ifndef NDEBUG +// Debugging helper for use within gdb +void WMLPageState::dump() +{ + WMLVariableMap::iterator it = m_variables.begin(); + WMLVariableMap::iterator end = m_variables.end(); + + fprintf(stderr, "Dumping WMLPageState (this=%p) associated with Page (page=%p)...\n", this, m_page); + for (; it != end; ++it) + fprintf(stderr, "\t-> name: '%s'\tvalue: '%s'\n", (*it).first.latin1().data(), (*it).second.latin1().data()); +} +#endif + +void WMLPageState::reset() +{ + // Remove all the variables + m_variables.clear(); + + // Clear the navigation history state + if (m_page) + m_page->backForward()->client()->clearWMLPageHistory(); +} + +static inline String normalizedHostName(const String& passedHost) +{ + if (passedHost.contains("127.0.0.1")) { + String host = passedHost; + return host.replace("127.0.0.1", "localhost"); + } + + return passedHost; +} + +static inline String hostFromURL(const KURL& url) +{ + // Default to "localhost" + String host = normalizedHostName(url.host()); + return host.isEmpty() ? "localhost" : host; +} + +static KURL urlForHistoryItem(Frame* frame, HistoryItem* item) +{ + // For LayoutTests we need to find the corresponding WML frame in the test document + // to be able to test access-control correctly. Remember that WML is never supposed + // to be embedded anywhere, so the purpose is to simulate a standalone WML document. + if (frame->document()->isWMLDocument()) + return item->url(); + + const HistoryItemVector& childItems = item->children(); + HistoryItemVector::const_iterator it = childItems.begin(); + const HistoryItemVector::const_iterator end = childItems.end(); + + for (; it != end; ++it) { + const RefPtr<HistoryItem> childItem = *it; + Frame* childFrame = frame->tree()->child(childItem->target()); + if (!childFrame) + continue; + + if (Document* childDocument = childFrame->document()) { + if (childDocument->isWMLDocument()) + return childItem->url(); + } + } + + return item->url(); +} + +static bool tryAccessHistoryURLs(Page* page, KURL& previousURL, KURL& currentURL) +{ + if (!page) + return false; + + Frame* frame = page->mainFrame(); + if (!frame || !frame->document()) + return false; + + HistoryItem* previousItem = page->backForward()->backItem(); + if (!previousItem) + return false; + + HistoryItem* currentItem = page->backForward()->currentItem(); + if (!currentItem) + return false; + + previousURL = urlForHistoryItem(frame, previousItem); + currentURL = urlForHistoryItem(frame, currentItem); + + return true; +} + +bool WMLPageState::processAccessControlData(const String& domain, const String& path) +{ + if (m_hasAccessControlData) + return false; + + m_hasAccessControlData = true; + + KURL previousURL, currentURL; + if (!tryAccessHistoryURLs(m_page, previousURL, currentURL)) + return true; + + // Spec: The path attribute defaults to the value "/" + m_accessPath = path.isEmpty() ? "/" : path; + + // Spec: The domain attribute defaults to the current decks domain. + String previousHost = hostFromURL(previousURL); + m_accessDomain = domain.isEmpty() ? previousHost : normalizedHostName(domain); + + // Spec: To simplify the development of applications that may not know the absolute path to the + // current deck, the path attribute accepts relative URIs. The user agent converts the relative + // path to an absolute path and then performs prefix matching against the PATH attribute. + Document* document = m_page->mainFrame() ? m_page->mainFrame()->document() : 0; + if (document && previousHost == m_accessDomain && !m_accessPath.startsWith("/")) { + String currentPath = currentURL.path(); + + size_t index = currentPath.reverseFind('/'); + if (index != WTF::notFound) + m_accessPath = document->completeURL(currentPath.left(index + 1) + m_accessPath).path(); + } + + return true; +} + +void WMLPageState::resetAccessControlData() +{ + m_hasAccessControlData = false; + m_accessDomain = String(); + m_accessPath = String(); +} + +bool WMLPageState::canAccessDeck() const +{ + if (!m_hasAccessControlData) + return true; + + KURL previousURL, currentURL; + if (!tryAccessHistoryURLs(m_page, previousURL, currentURL)) + return true; + + if (equalIgnoringFragmentIdentifier(previousURL, currentURL)) + return true; + + return hostIsAllowedToAccess(hostFromURL(previousURL)) && pathIsAllowedToAccess(previousURL.path()); +} + +bool WMLPageState::hostIsAllowedToAccess(const String& host) const +{ + // Spec: The access domain is suffix-matched against the domain name portion of the referring URI + Vector<String> subdomainsAllowed; + if (m_accessDomain.contains('.')) + m_accessDomain.split('.', subdomainsAllowed); + else + subdomainsAllowed.append(m_accessDomain); + + Vector<String> subdomainsCheck; + if (host.contains('.')) + host.split('.', subdomainsCheck); + else + subdomainsCheck.append(host); + + Vector<String>::iterator itAllowed = subdomainsAllowed.end() - 1; + Vector<String>::iterator beginAllowed = subdomainsAllowed.begin(); + + Vector<String>::iterator itCheck = subdomainsCheck.end() - 1; + Vector<String>::iterator beginCheck = subdomainsCheck.begin(); + + bool hostOk = true; + for (; itAllowed >= beginAllowed && itCheck >= beginCheck; ) { + if (*itAllowed != *itCheck) { + hostOk = false; + break; + } + + --itAllowed; + --itCheck; + } + + return hostOk; +} + +bool WMLPageState::pathIsAllowedToAccess(const String& path) const +{ + // Spec: The access path is prefix matched against the path portion of the referring URI + Vector<String> subpathsAllowed; + if (m_accessPath.contains('/')) + m_accessPath.split('/', subpathsAllowed); + else + subpathsAllowed.append(m_accessPath); + + Vector<String> subpathsCheck; + if (path.contains('/')) + path.split('/', subpathsCheck); + else + subpathsCheck.append(path); + + Vector<String>::iterator itAllowed = subpathsAllowed.begin(); + Vector<String>::iterator endAllowed = subpathsAllowed.end(); + + Vector<String>::iterator itCheck = subpathsCheck.begin(); + Vector<String>::iterator endCheck = subpathsCheck.end(); + + bool pathOk = true; + for (; itAllowed != endAllowed && itCheck != endCheck; ) { + if (*itAllowed != *itCheck) { + pathOk = false; + break; + } + + ++itAllowed; + ++itCheck; + } + + return pathOk; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLPageState.h b/Source/WebCore/wml/WMLPageState.h new file mode 100644 index 0000000..0ea7cbb --- /dev/null +++ b/Source/WebCore/wml/WMLPageState.h @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * Copyright (C) 2004-2007 Apple Inc. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLPageState_h +#define WMLPageState_h + +#if ENABLE(WML) +#include <wtf/Forward.h> +#include <wtf/HashMap.h> +#include <wtf/text/StringHash.h> + +namespace WebCore { + +class Page; +class WMLCardElement; + +typedef HashMap<String, String> WMLVariableMap; + +class WMLPageState { +public: + WMLPageState(Page*); + virtual ~WMLPageState(); + +#ifndef NDEBUG + void dump(); +#endif + + // Reset the browser context + void reset(); + + // Variable handling + void storeVariable(const String& name, const String& value) { m_variables.set(name, value); } + void storeVariables(WMLVariableMap& variables) { m_variables = variables; } + String getVariable(const String& name) const { return m_variables.get(name); } + bool hasVariables() const { return !m_variables.isEmpty(); } + + Page* page() const { return m_page; } + + // Deck access control + bool processAccessControlData(const String& dmain, const String& path); + void resetAccessControlData(); + + bool canAccessDeck() const; + +private: + bool hostIsAllowedToAccess(const String&) const; + bool pathIsAllowedToAccess(const String&) const; + +private: + Page* m_page; + WMLVariableMap m_variables; + String m_accessDomain; + String m_accessPath; + bool m_hasAccessControlData; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLPostfieldElement.cpp b/Source/WebCore/wml/WMLPostfieldElement.cpp new file mode 100644 index 0000000..25ce05a --- /dev/null +++ b/Source/WebCore/wml/WMLPostfieldElement.cpp @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLPostfieldElement.h" + +#include "TextEncoding.h" +#include "HTMLNames.h" +#include "WMLDocument.h" +#include "WMLGoElement.h" +#include "WMLNames.h" +#include <wtf/text/CString.h> + +namespace WebCore { + +using namespace WMLNames; + +WMLPostfieldElement::WMLPostfieldElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLPostfieldElement> WMLPostfieldElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLPostfieldElement(tagName, document)); +} + +void WMLPostfieldElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + ContainerNode* parent = parentNode(); + if (parent && parent->hasTagName(goTag)) + static_cast<WMLGoElement*>(parent)->registerPostfieldElement(this); +} + +void WMLPostfieldElement::removedFromDocument() +{ + ContainerNode* parent = parentNode(); + if (parent && parent->hasTagName(goTag)) + static_cast<WMLGoElement*>(parent)->deregisterPostfieldElement(this); + + WMLElement::removedFromDocument(); +} + +String WMLPostfieldElement::name() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::nameAttr)); +} + +String WMLPostfieldElement::value() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr)); +} + +static inline CString encodedString(const TextEncoding& encoding, const String& data) +{ + return encoding.encode(data.characters(), data.length(), EntitiesForUnencodables); +} + +void WMLPostfieldElement::encodeData(const TextEncoding& encoding, CString& name, CString& value) +{ + name = encodedString(encoding, this->name()); + value = encodedString(encoding, this->value()); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLPostfieldElement.h b/Source/WebCore/wml/WMLPostfieldElement.h new file mode 100644 index 0000000..8d91073 --- /dev/null +++ b/Source/WebCore/wml/WMLPostfieldElement.h @@ -0,0 +1,48 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLPostfieldElement_h +#define WMLPostfieldElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLPostfieldElement : public WMLElement { +public: + static PassRefPtr<WMLPostfieldElement> create(const QualifiedName&, Document*); + + WMLPostfieldElement(const QualifiedName& tagName, Document*); + + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + + String name() const; + String value() const; + + // Encode name() and value() in a CString using the passed encoding + void encodeData(const TextEncoding&, CString& name, CString& value); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLPrevElement.cpp b/Source/WebCore/wml/WMLPrevElement.cpp new file mode 100644 index 0000000..c07f019 --- /dev/null +++ b/Source/WebCore/wml/WMLPrevElement.cpp @@ -0,0 +1,73 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLPrevElement.h" + +#include "BackForwardController.h" +#include "Page.h" +#include "WMLCardElement.h" +#include "WMLDocument.h" +#include "WMLPageState.h" +#include "WMLTimerElement.h" + +namespace WebCore { + +WMLPrevElement::WMLPrevElement(const QualifiedName& tagName, Document* doc) + : WMLTaskElement(tagName, doc) +{ +} + +PassRefPtr<WMLPrevElement> WMLPrevElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLPrevElement(tagName, document)); +} + +WMLPrevElement::~WMLPrevElement() +{ +} + +void WMLPrevElement::executeTask() +{ + ASSERT(document()->isWMLDocument()); + WMLDocument* document = static_cast<WMLDocument*>(this->document()); + + WMLPageState* pageState = wmlPageStateForDocument(document); + if (!pageState) + return; + + WMLCardElement* card = document->activeCard(); + if (!card) + return; + + storeVariableState(pageState); + + // Stop the timer of the current card if it is active + if (WMLTimerElement* eventTimer = card->eventTimer()) + eventTimer->stop(); + + pageState->page()->backForward()->goBack(); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLPrevElement.h b/Source/WebCore/wml/WMLPrevElement.h new file mode 100644 index 0000000..2db8166 --- /dev/null +++ b/Source/WebCore/wml/WMLPrevElement.h @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLPrevElement_h +#define WMLPrevElement_h + +#if ENABLE(WML) +#include "WMLTaskElement.h" + +namespace WebCore { + +class WMLPrevElement : public WMLTaskElement { +public: + static PassRefPtr<WMLPrevElement> create(const QualifiedName&, Document*); + + WMLPrevElement(const QualifiedName& tagName, Document*); + virtual ~WMLPrevElement(); + + virtual void executeTask(); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLRefreshElement.cpp b/Source/WebCore/wml/WMLRefreshElement.cpp new file mode 100644 index 0000000..8267e20 --- /dev/null +++ b/Source/WebCore/wml/WMLRefreshElement.cpp @@ -0,0 +1,85 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLRefreshElement.h" + +#include "Frame.h" +#include "FrameLoader.h" +#include "WMLCardElement.h" +#include "WMLDocument.h" +#include "WMLPageState.h" +#include "WMLTimerElement.h" + +namespace WebCore { + +WMLRefreshElement::WMLRefreshElement(const QualifiedName& tagName, Document* doc) + : WMLTaskElement(tagName, doc) +{ +} + +PassRefPtr<WMLRefreshElement> WMLRefreshElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLRefreshElement(tagName, document)); +} + +WMLRefreshElement::~WMLRefreshElement() +{ +} + +void WMLRefreshElement::executeTask() +{ + ASSERT(document()->isWMLDocument()); + WMLDocument* document = static_cast<WMLDocument*>(this->document()); + + WMLPageState* pageState = wmlPageStateForDocument(document); + if (!pageState) + return; + + WMLCardElement* card = document->activeCard(); + if (!card) + return; + + // Before perform refresh task, we store the current timeout + // value in the page state and then stop the timer + WMLTimerElement* timer = card->eventTimer(); + if (timer) { + timer->storeIntervalToPageState(); + timer->stop(); + } + + storeVariableState(pageState); + + // Redisplay curremt card with current variable state + if (Frame* frame = document->frame()) { + if (FrameLoader* loader = frame->loader()) + loader->reload(); + } + + // After refreshing task, resume the timer if it exsits + if (timer) + timer->start(); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLRefreshElement.h b/Source/WebCore/wml/WMLRefreshElement.h new file mode 100644 index 0000000..1459a05 --- /dev/null +++ b/Source/WebCore/wml/WMLRefreshElement.h @@ -0,0 +1,42 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLRefreshElement_h +#define WMLRefreshElement_h + +#if ENABLE(WML) +#include "WMLTaskElement.h" + +namespace WebCore { + +class WMLRefreshElement : public WMLTaskElement { +public: + static PassRefPtr<WMLRefreshElement> create(const QualifiedName&, Document*); + + WMLRefreshElement(const QualifiedName& tagName, Document*); + virtual ~WMLRefreshElement(); + + virtual void executeTask(); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLSelectElement.cpp b/Source/WebCore/wml/WMLSelectElement.cpp new file mode 100644 index 0000000..78749b3 --- /dev/null +++ b/Source/WebCore/wml/WMLSelectElement.cpp @@ -0,0 +1,562 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLSelectElement.h" + +#include "Attribute.h" +#include "HTMLNames.h" +#include "OptionElement.h" +#include "RenderListBox.h" +#include "RenderMenuList.h" +#include "WMLDocument.h" +#include "WMLNames.h" +#include "WMLVariables.h" +#include <wtf/StdLibExtras.h> +#include <wtf/text/CString.h> + +namespace WebCore { + +using namespace WMLNames; + +WMLSelectElement::WMLSelectElement(const QualifiedName& tagName, Document* document) + : WMLFormControlElement(tagName, document) + , m_initialized(false) +{ +} + +PassRefPtr<WMLSelectElement> WMLSelectElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLSelectElement(tagName, document)); +} + +WMLSelectElement::~WMLSelectElement() +{ +} + +const AtomicString& WMLSelectElement::formControlName() const +{ + AtomicString name = this->name(); + return name.isNull() ? emptyAtom : name; +} + +const AtomicString& WMLSelectElement::formControlType() const +{ + DEFINE_STATIC_LOCAL(const AtomicString, selectMultiple, ("select-multiple")); + DEFINE_STATIC_LOCAL(const AtomicString, selectOne, ("select-one")); + return m_data.multiple() ? selectMultiple : selectOne; +} + +bool WMLSelectElement::isKeyboardFocusable(KeyboardEvent* event) const +{ + if (renderer()) + return isFocusable(); + + return WMLFormControlElement::isKeyboardFocusable(event); +} + +bool WMLSelectElement::isMouseFocusable() const +{ + if (renderer()) + return isFocusable(); + + return WMLFormControlElement::isMouseFocusable(); +} + +void WMLSelectElement::selectAll() +{ + SelectElement::selectAll(m_data, this); +} + +void WMLSelectElement::recalcStyle(StyleChange change) +{ + WMLFormControlElement::recalcStyle(change); +} + +void WMLSelectElement::dispatchFocusEvent() +{ + SelectElement::dispatchFocusEvent(m_data, this); + WMLFormControlElement::dispatchFocusEvent(); +} + +void WMLSelectElement::dispatchBlurEvent() +{ + SelectElement::dispatchBlurEvent(m_data, this); + WMLFormControlElement::dispatchBlurEvent(); +} + +int WMLSelectElement::selectedIndex() const +{ + return SelectElement::selectedIndex(m_data, this); +} + +void WMLSelectElement::setSelectedIndex(int optionIndex, bool deselect) +{ + SelectElement::setSelectedIndex(m_data, this, optionIndex, deselect, false, false); +} + +void WMLSelectElement::setSelectedIndexByUser(int optionIndex, bool deselect, bool fireOnChangeNow, bool allowMultipleSelection) +{ + UNUSED_PARAM(allowMultipleSelection); + SelectElement::setSelectedIndex(m_data, this, optionIndex, deselect, fireOnChangeNow, true); +} + +bool WMLSelectElement::saveFormControlState(String& value) const +{ + return SelectElement::saveFormControlState(m_data, this, value); +} + +void WMLSelectElement::restoreFormControlState(const String& state) +{ + SelectElement::restoreFormControlState(m_data, this, state); +} + +void WMLSelectElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) +{ + SelectElement::setRecalcListItems(m_data, this); + WMLFormControlElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); +} + +void WMLSelectElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::multipleAttr) + SelectElement::parseMultipleAttribute(m_data, this, attr); + else + WMLFormControlElement::parseMappedAttribute(attr); +} + +RenderObject* WMLSelectElement::createRenderer(RenderArena* arena, RenderStyle*) +{ + if (m_data.usesMenuList()) + return new (arena) RenderMenuList(this); + return new (arena) RenderListBox(this); +} + +bool WMLSelectElement::appendFormData(FormDataList& list, bool) +{ + return SelectElement::appendFormData(m_data, this, list); +} + +int WMLSelectElement::optionToListIndex(int optionIndex) const +{ + return SelectElement::optionToListIndex(m_data, this, optionIndex); +} + +int WMLSelectElement::listToOptionIndex(int listIndex) const +{ + return SelectElement::listToOptionIndex(m_data, this, listIndex); +} + +void WMLSelectElement::reset() +{ + SelectElement::reset(m_data, this); +} + +void WMLSelectElement::defaultEventHandler(Event* event) +{ + SelectElement::defaultEventHandler(m_data, this, event, 0); + + // FIXME: There must be a better place to update the page variable state. Investigate. + updateVariables(); + + if (event->defaultHandled()) + return; + + WMLFormControlElement::defaultEventHandler(event); +} + +void WMLSelectElement::accessKeyAction(bool sendToAnyElement) +{ + focus(); + dispatchSimulatedClick(0, sendToAnyElement); +} + +void WMLSelectElement::setActiveSelectionAnchorIndex(int index) +{ + SelectElement::setActiveSelectionAnchorIndex(m_data, this, index); +} + +void WMLSelectElement::setActiveSelectionEndIndex(int index) +{ + SelectElement::setActiveSelectionEndIndex(m_data, index); +} + +void WMLSelectElement::updateListBoxSelection(bool deselectOtherOptions) +{ + SelectElement::updateListBoxSelection(m_data, this, deselectOtherOptions); +} + +void WMLSelectElement::listBoxOnChange() +{ + SelectElement::listBoxOnChange(m_data, this); +} + +void WMLSelectElement::menuListOnChange() +{ + SelectElement::menuListOnChange(m_data, this); +} + +int WMLSelectElement::activeSelectionStartListIndex() const +{ + if (m_data.activeSelectionAnchorIndex() >= 0) + return m_data.activeSelectionAnchorIndex(); + return optionToListIndex(selectedIndex()); +} + +int WMLSelectElement::activeSelectionEndListIndex() const +{ + if (m_data.activeSelectionEndIndex() >= 0) + return m_data.activeSelectionEndIndex(); + return SelectElement::lastSelectedListIndex(m_data, this); +} + +void WMLSelectElement::accessKeySetSelectedIndex(int index) +{ + SelectElement::accessKeySetSelectedIndex(m_data, this, index); +} + +void WMLSelectElement::setRecalcListItems() +{ + SelectElement::setRecalcListItems(m_data, this); +} + +void WMLSelectElement::scrollToSelection() +{ + SelectElement::scrollToSelection(m_data, this); +} + +void WMLSelectElement::selectInitialOptions() +{ + // Spec: Step 1 - the default option index is determined using iname and ivalue + calculateDefaultOptionIndices(); + + if (m_defaultOptionIndices.isEmpty()) { + m_initialized = true; + return; + } + + // Spec: Step 2 – initialise variables + initializeVariables(); + + // Spec: Step 3 – pre-select option(s) specified by the default option index + selectDefaultOptions(); + m_initialized = true; +} + +void WMLSelectElement::insertedIntoTree(bool deep) +{ + SelectElement::insertedIntoTree(m_data, this); + WMLFormControlElement::insertedIntoTree(deep); +} + +void WMLSelectElement::calculateDefaultOptionIndices() +{ + WMLPageState* pageState = wmlPageStateForDocument(document()); + if (!pageState) + return; + + String variable; + + // Spec: If the 'iname' attribute is specified and names a variable that is set, + // then the default option index is the validated value of that variable. + String iname = this->iname(); + if (!iname.isEmpty()) { + variable = pageState->getVariable(iname); + if (!variable.isEmpty()) + m_defaultOptionIndices = parseIndexValueString(variable); + } + + // Spec: If the default option index is empty and the 'ivalue' attribute is specified, + // then the default option index is the validated attribute value. + String ivalue = this->ivalue(); + if (m_defaultOptionIndices.isEmpty() && !ivalue.isEmpty()) + m_defaultOptionIndices = parseIndexValueString(ivalue); + + // Spec: If the default option index is empty, and the 'name' attribute is specified + // and the 'name' ttribute names a variable that is set, then for each value in the 'name' + // variable that is present as a value in the select's option elements, the index of the + // first option element containing that value is added to the default index if that + // index has not been previously added. + String name = this->name(); + if (m_defaultOptionIndices.isEmpty() && !name.isEmpty()) { + variable = pageState->getVariable(name); + if (!variable.isEmpty()) + m_defaultOptionIndices = valueStringToOptionIndices(variable); + } + + String value = parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr)); + + // Spec: If the default option index is empty and the 'value' attribute is specified then + // for each value in the 'value' attribute that is present as a value in the select's + // option elements, the index of the first option element containing that value is added + // to the default index if that index has not been previously added. + if (m_defaultOptionIndices.isEmpty() && !value.isEmpty()) + m_defaultOptionIndices = valueStringToOptionIndices(value); + + // Spec: If the default option index is empty and the select is a multi-choice, then the + // default option index is set to zero. If the select is single-choice, then the default + // option index is set to one. + if (m_defaultOptionIndices.isEmpty()) + m_defaultOptionIndices.append((unsigned) !m_data.multiple()); +} + +void WMLSelectElement::selectDefaultOptions() +{ + ASSERT(!m_defaultOptionIndices.isEmpty()); + + if (!m_data.multiple()) { + setSelectedIndex(m_defaultOptionIndices.first() - 1, false); + return; + } + + Vector<unsigned>::const_iterator end = m_defaultOptionIndices.end(); + for (Vector<unsigned>::const_iterator it = m_defaultOptionIndices.begin(); it != end; ++it) + setSelectedIndex((*it) - 1, false); +} + +void WMLSelectElement::initializeVariables() +{ + ASSERT(!m_defaultOptionIndices.isEmpty()); + + WMLPageState* pageState = wmlPageStateForDocument(document()); + if (!pageState) + return; + + const Vector<Element*>& items = m_data.listItems(this); + if (items.isEmpty()) + return; + + // Spec: If the 'iname' attribute is specified, then the named variable is set with the default option index. + String iname = this->iname(); + if (!iname.isEmpty()) + pageState->storeVariable(iname, optionIndicesToString()); + + String name = this->name(); + if (name.isEmpty()) + return; + + if (m_data.multiple()) { + // Spec: If the 'name' attribute is specified and the select is a multiple-choice element, + // then for each index greater than zero, the value of the 'value' attribute on the option + // element at the index is added to the name variable. + pageState->storeVariable(name, optionIndicesToValueString()); + return; + } + + // Spec: If the 'name' attribute is specified and the select is a single-choice element, + // then the named variable is set with the value of the 'value' attribute on the option + // element at the default option index. + unsigned optionIndex = m_defaultOptionIndices.first(); + ASSERT(optionIndex >= 1); + + int listIndex = optionToListIndex(optionIndex - 1); + ASSERT(listIndex >= 0); + ASSERT(listIndex < (int) items.size()); + + if (OptionElement* optionElement = toOptionElement(items[listIndex])) + pageState->storeVariable(name, optionElement->value()); +} + +void WMLSelectElement::updateVariables() +{ + WMLPageState* pageState = wmlPageStateForDocument(document()); + if (!pageState) + return; + + String name = this->name(); + String iname = this->iname(); + if (iname.isEmpty() && name.isEmpty()) + return; + + String nameString; + String inameString; + + unsigned optionIndex = 0; + const Vector<Element*>& items = m_data.listItems(this); + + for (unsigned i = 0; i < items.size(); ++i) { + OptionElement* optionElement = toOptionElement(items[i]); + if (!optionElement) + continue; + + ++optionIndex; + if (!optionElement->selected()) + continue; + + if (!nameString.isEmpty()) + nameString += ";"; + + if (!inameString.isEmpty()) + inameString += ";"; + + nameString += optionElement->value(); + inameString += String::number(optionIndex); + } + + if (!name.isEmpty()) + pageState->storeVariable(name, nameString); + + if (!iname.isEmpty()) + pageState->storeVariable(iname, inameString); +} + +Vector<unsigned> WMLSelectElement::parseIndexValueString(const String& indexValue) const +{ + Vector<unsigned> indices; + if (indexValue.isEmpty()) + return indices; + + Vector<String> indexStrings; + indexValue.split(';', indexStrings); + + bool ok = false; + unsigned optionCount = SelectElement::optionCount(m_data, this); + + Vector<String>::const_iterator end = indexStrings.end(); + for (Vector<String>::const_iterator it = indexStrings.begin(); it != end; ++it) { + unsigned parsedValue = (*it).toUIntStrict(&ok); + // Spec: Remove all non-integer indices from the value. Remove all out-of-range indices + // from the value, where out-of-range is defined as any index with a value greater than + // the number of options in the select or with a value less than one. + if (!ok || parsedValue < 1 || parsedValue > optionCount) + continue; + + // Spec: Remove duplicate indices. + if (indices.find(parsedValue) == notFound) + indices.append(parsedValue); + } + + return indices; +} + +Vector<unsigned> WMLSelectElement::valueStringToOptionIndices(const String& value) const +{ + Vector<unsigned> indices; + if (value.isEmpty()) + return indices; + + const Vector<Element*>& items = m_data.listItems(this); + if (items.isEmpty()) + return indices; + + Vector<String> indexStrings; + value.split(';', indexStrings); + + unsigned optionIndex = 0; + + Vector<String>::const_iterator end = indexStrings.end(); + for (Vector<String>::const_iterator it = indexStrings.begin(); it != end; ++it) { + String value = *it; + + for (unsigned i = 0; i < items.size(); ++i) { + if (!isOptionElement(items[i])) + continue; + + ++optionIndex; + if (OptionElement* optionElement = toOptionElement(items[i])) { + if (optionElement->value() == value) { + indices.append(optionIndex); + break; + } + } + } + } + + return indices; +} + +String WMLSelectElement::optionIndicesToValueString() const +{ + String valueString; + if (m_defaultOptionIndices.isEmpty()) + return valueString; + + const Vector<Element*>& items = m_data.listItems(this); + if (items.isEmpty()) + return valueString; + + Vector<unsigned>::const_iterator end = m_defaultOptionIndices.end(); + for (Vector<unsigned>::const_iterator it = m_defaultOptionIndices.begin(); it != end; ++it) { + unsigned optionIndex = (*it); + if (optionIndex < 1 || optionIndex > items.size()) + continue; + + int listIndex = optionToListIndex((*it) - 1); + ASSERT(listIndex >= 0); + ASSERT(listIndex < (int) items.size()); + + if (OptionElement* optionElement = toOptionElement(items[listIndex])) { + if (!valueString.isEmpty()) + valueString += ";"; + + valueString += optionElement->value(); + } + } + + return valueString; +} + +String WMLSelectElement::optionIndicesToString() const +{ + String valueString; + if (m_defaultOptionIndices.isEmpty()) + return valueString; + + Vector<unsigned>::const_iterator end = m_defaultOptionIndices.end(); + for (Vector<unsigned>::const_iterator it = m_defaultOptionIndices.begin(); it != end; ++it) { + if (!valueString.isEmpty()) + valueString += ";"; + + valueString += String::number(*it); + } + + return valueString; +} + +String WMLSelectElement::name() const +{ + return parseValueForbiddingVariableReferences(getAttribute(HTMLNames::nameAttr)); +} + +String WMLSelectElement::value() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr)); +} + +String WMLSelectElement::iname() const +{ + return parseValueForbiddingVariableReferences(getAttribute(inameAttr)); +} + +String WMLSelectElement::ivalue() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(ivalueAttr)); +} + +void WMLSelectElement::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow) +{ + /* Dummy implementation as listBoxSelectItem is pure virtual in SelectElement class */ +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLSelectElement.h b/Source/WebCore/wml/WMLSelectElement.h new file mode 100644 index 0000000..3d8c726 --- /dev/null +++ b/Source/WebCore/wml/WMLSelectElement.h @@ -0,0 +1,121 @@ +/** + * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLSelectElement_h +#define WMLSelectElement_h + +#if ENABLE(WML) +#include "WMLFormControlElement.h" +#include "SelectElement.h" + +namespace WebCore { + +class WMLSelectElement : public WMLFormControlElement, public SelectElement { +public: + static PassRefPtr<WMLSelectElement> create(const QualifiedName&, Document*); + + WMLSelectElement(const QualifiedName&, Document*); + virtual ~WMLSelectElement(); + + virtual const AtomicString& formControlName() const; + virtual const AtomicString& formControlType() const; + + virtual bool isKeyboardFocusable(KeyboardEvent*) const; + virtual bool isMouseFocusable() const; + virtual bool canSelectAll() const { return !m_data.usesMenuList(); } + virtual void selectAll(); + + virtual void recalcStyle(StyleChange); + + virtual void dispatchFocusEvent(); + virtual void dispatchBlurEvent(); + + virtual bool canStartSelection() const { return false; } + + virtual int selectedIndex() const; + virtual void setSelectedIndex(int index, bool deselect = true); + virtual void setSelectedIndexByUser(int index, bool deselect = true, bool fireOnChangeNow = false, bool allowMultipleSelection = false); + + virtual int size() const { return m_data.size(); } + virtual bool multiple() const { return m_data.multiple(); } + + virtual bool saveFormControlState(String& value) const; + virtual void restoreFormControlState(const String&); + + virtual void childrenChanged(bool changedByParser = false, Node* beforeChange = 0, Node* afterChange = 0, int childCountDelta = 0); + + virtual void parseMappedAttribute(Attribute*); + + virtual RenderObject* createRenderer(RenderArena*, RenderStyle*); + virtual bool appendFormData(FormDataList&, bool); + virtual int optionToListIndex(int optionIndex) const; + virtual int listToOptionIndex(int listIndex) const; + + virtual const Vector<Element*>& listItems() const { return m_data.listItems(this); } + virtual void reset(); + + virtual void defaultEventHandler(Event*); + virtual void accessKeyAction(bool sendToAnyElement); + virtual void setActiveSelectionAnchorIndex(int index); + virtual void setActiveSelectionEndIndex(int index); + virtual void updateListBoxSelection(bool deselectOtherOptions); + virtual void listBoxOnChange(); + virtual void menuListOnChange(); + + virtual int activeSelectionStartListIndex() const; + virtual int activeSelectionEndListIndex() const; + + void accessKeySetSelectedIndex(int); + void setRecalcListItems(); + void scrollToSelection(); + void selectInitialOptions(); + + bool initialized() const { return m_initialized; } + + virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true); +private: + virtual void insertedIntoTree(bool); + + void calculateDefaultOptionIndices(); + void selectDefaultOptions(); + void initializeVariables(); + void updateVariables(); + + Vector<unsigned> parseIndexValueString(const String&) const; + Vector<unsigned> valueStringToOptionIndices(const String&) const; + String optionIndicesToValueString() const; + String optionIndicesToString() const; + + virtual void updateValidity() {} + + String name() const; + String value() const; + String iname() const; + String ivalue() const; + + SelectElementData m_data; + bool m_initialized; + Vector<unsigned> m_defaultOptionIndices; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLSetvarElement.cpp b/Source/WebCore/wml/WMLSetvarElement.cpp new file mode 100644 index 0000000..0514602 --- /dev/null +++ b/Source/WebCore/wml/WMLSetvarElement.cpp @@ -0,0 +1,94 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLSetvarElement.h" + +#include "Attribute.h" +#include "HTMLNames.h" +#include "WMLErrorHandling.h" +#include "WMLTaskElement.h" +#include "WMLVariables.h" + +namespace WebCore { + +WMLSetvarElement::WMLSetvarElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +PassRefPtr<WMLSetvarElement> WMLSetvarElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLSetvarElement(tagName, document)); +} + +WMLSetvarElement::~WMLSetvarElement() +{ +} + +void WMLSetvarElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::nameAttr) { + if (!isValidVariableName(parseValueSubstitutingVariableReferences(attr->value(), WMLErrorInvalidVariableName))) { + reportWMLError(document(), WMLErrorInvalidVariableName); + return; + } + } else + WMLElement::parseMappedAttribute(attr); +} + +void WMLSetvarElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + ContainerNode* parent = parentNode(); + if (!parent || !parent->isWMLElement()) + return; + + if (static_cast<WMLElement*>(parent)->isWMLTaskElement()) + static_cast<WMLTaskElement*>(parent)->registerVariableSetter(this); +} + +void WMLSetvarElement::removedFromDocument() +{ + ContainerNode* parent = parentNode(); + if (parent && parent->isWMLElement()) { + if (static_cast<WMLElement*>(parent)->isWMLTaskElement()) + static_cast<WMLTaskElement*>(parent)->deregisterVariableSetter(this); + } + + WMLElement::removedFromDocument(); +} + +String WMLSetvarElement::name() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::nameAttr), WMLErrorInvalidVariableName); +} + +String WMLSetvarElement::value() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr)); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLSetvarElement.h b/Source/WebCore/wml/WMLSetvarElement.h new file mode 100644 index 0000000..0951360 --- /dev/null +++ b/Source/WebCore/wml/WMLSetvarElement.h @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLSetvarElement_h +#define WMLSetvarElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class WMLSetvarElement : public WMLElement { +public: + static PassRefPtr<WMLSetvarElement> create(const QualifiedName&, Document*); + + WMLSetvarElement(const QualifiedName& tagName, Document*); + virtual ~WMLSetvarElement(); + + virtual void parseMappedAttribute(Attribute*); + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + + String name() const; + String value() const; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLTableElement.cpp b/Source/WebCore/wml/WMLTableElement.cpp new file mode 100644 index 0000000..ed3522d --- /dev/null +++ b/Source/WebCore/wml/WMLTableElement.cpp @@ -0,0 +1,275 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLTableElement.h" + +#include "Attribute.h" +#include "CSSPropertyNames.h" +#include "CSSValueKeywords.h" +#include "CharacterNames.h" +#include "Document.h" +#include "HTMLNames.h" +#include "NodeList.h" +#include "RenderObject.h" +#include "Text.h" +#include "WMLErrorHandling.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLTableElement::WMLTableElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) + , m_columns(0) +{ +} + +PassRefPtr<WMLTableElement> WMLTableElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLTableElement(tagName, document)); +} + +WMLTableElement::~WMLTableElement() +{ +} + +bool WMLTableElement::mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const +{ + if (attrName == HTMLNames::alignAttr) { + result = eTable; + return false; + } + + return WMLElement::mapToEntry(attrName, result); +} + +void WMLTableElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == columnsAttr) { + bool isNumber = false; + m_columns = attr->value().string().toUIntStrict(&isNumber); + + // Spec: This required attribute specifies the number of columns for the table. + // The user agent must create a table with exactly the number of columns specified + // by the attribute value. It is an error to specify a value of zero ("0") + if (!m_columns || !isNumber) + reportWMLError(document(), WMLErrorInvalidColumnsNumberInTable); + } else if (attr->name() == HTMLNames::alignAttr) + m_alignment = parseValueForbiddingVariableReferences(attr->value()); + else + WMLElement::parseMappedAttribute(attr); +} + +void WMLTableElement::finishParsingChildren() +{ + WMLElement::finishParsingChildren(); + + if (!m_columns) { + reportWMLError(document(), WMLErrorInvalidColumnsNumberInTable); + return; + } + + Vector<WMLElement*> rowElements = scanTableChildElements(this, trTag); + if (rowElements.isEmpty()) + return; + + Vector<WMLElement*>::iterator it = rowElements.begin(); + Vector<WMLElement*>::iterator end = rowElements.end(); + + for (; it != end; ++it) { + WMLElement* rowElement = (*it); + + // Squeeze the table to fit in the desired number of columns + Vector<WMLElement*> columnElements = scanTableChildElements(rowElement, tdTag); + unsigned actualNumberOfColumns = columnElements.size(); + + if (actualNumberOfColumns > m_columns) { + joinSuperflousColumns(columnElements, rowElement); + columnElements = scanTableChildElements(rowElement, tdTag); + } else if (actualNumberOfColumns < m_columns) { + padWithEmptyColumns(columnElements, rowElement); + columnElements = scanTableChildElements(rowElement, tdTag); + } + + // Layout cells according to the 'align' attribute + alignCells(columnElements, rowElement); + } +} + +Vector<WMLElement*> WMLTableElement::scanTableChildElements(WMLElement* startElement, const QualifiedName& tagName) const +{ + Vector<WMLElement*> childElements; + + RefPtr<NodeList> children = startElement->childNodes(); + if (!children) + return childElements; + + unsigned length = children->length(); + for (unsigned i = 0; i < length; ++i) { + Node* child = children->item(i); + if (child->hasTagName(tagName)) + childElements.append(static_cast<WMLElement*>(child)); + } + + return childElements; +} + +void WMLTableElement::transferAllChildrenOfElementToTargetElement(WMLElement* sourceElement, WMLElement* targetElement, unsigned startOffset) const +{ + RefPtr<NodeList> children = sourceElement->childNodes(); + if (!children) + return; + + ExceptionCode ec = 0; + + unsigned length = children->length(); + for (unsigned i = startOffset; i < length; ++i) { + RefPtr<Node> clonedNode = children->item(i)->cloneNode(true); + targetElement->appendChild(clonedNode.release(), ec); + ASSERT(ec == 0); + } +} + +bool WMLTableElement::tryMergeAdjacentTextCells(Node* item, Node* nextItem) const +{ + if (!item || !nextItem) + return false; + + if (!item->isTextNode() || !nextItem->isTextNode()) + return false; + + Text* itemText = static_cast<Text*>(item); + Text* nextItemText = static_cast<Text*>(nextItem); + + String newContent = " "; + newContent += nextItemText->data(); + + ExceptionCode ec = 0; + itemText->appendData(newContent, ec); + ASSERT(ec == 0); + + return true; +} + +void WMLTableElement::joinSuperflousColumns(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const +{ + // Spec: If the actual number of columns in a row is greater than the value specified + // by this attribute, the extra columns of the row must be aggregated into the last + // column such that the row contains exactly the number of columns specified. + WMLElement* lastColumn = columnElements.at(m_columns - 1); + ASSERT(lastColumn); + + // Merge superflous columns into a single one + RefPtr<WMLElement> newCell = WMLElement::create(tdTag, document()); + transferAllChildrenOfElementToTargetElement(lastColumn, newCell.get(), 0); + + ExceptionCode ec = 0; + unsigned actualNumberOfColumns = columnElements.size(); + + for (unsigned i = m_columns; i < actualNumberOfColumns; ++i) { + WMLElement* columnElement = columnElements.at(i); + unsigned startOffset = 0; + + // Spec: A single inter-word space must be inserted between two cells that are being aggregated. + if (tryMergeAdjacentTextCells(newCell->lastChild(), columnElement->firstChild())) + ++startOffset; + + transferAllChildrenOfElementToTargetElement(columnElement, newCell.get(), startOffset); + } + + // Remove the columns, that have just been merged + unsigned i = actualNumberOfColumns; + for (; i > m_columns; --i) { + rowElement->removeChild(columnElements.at(i - 1), ec); + ASSERT(ec == 0); + } + + // Replace the last column in the row with the new merged column + rowElement->replaceChild(newCell.release(), lastColumn, ec); + ASSERT(ec == 0); +} + +void WMLTableElement::padWithEmptyColumns(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const +{ + // Spec: If the actual number of columns in a row is less than the value specified by the columns + // attribute, the row must be padded with empty columns effectively as if the user agent + // appended empty td elements to the row. + ExceptionCode ec = 0; + + for (unsigned i = columnElements.size(); i < m_columns; ++i) { + RefPtr<WMLElement> newCell = WMLElement::create(tdTag, document()); + rowElement->appendChild(newCell.release(), ec); + ASSERT(ec == 0); + } +} + +void WMLTableElement::alignCells(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const +{ + // Spec: User agents should consider the current language when determining + // the default alignment and the direction of the table. + bool rtl = false; + if (RenderObject* renderer = rowElement->renderer()) { + if (RenderStyle* style = renderer->style()) + rtl = !style->isLeftToRightDirection(); + } + + rowElement->setAttribute(HTMLNames::alignAttr, rtl ? "right" : "left"); + + if (m_alignment.isEmpty()) + return; + + unsigned alignLength = m_alignment.length(); + + Vector<WMLElement*>::iterator it = columnElements.begin(); + Vector<WMLElement*>::iterator end = columnElements.end(); + + for (unsigned i = 0; it != end; ++it, ++i) { + if (i == alignLength) + break; + + String alignmentValue; + switch (m_alignment[i]) { + case 'C': + alignmentValue = "center"; + break; + case 'L': + alignmentValue = "left"; + break; + case 'R': + alignmentValue = "right"; + break; + default: + break; + } + + if (alignmentValue.isEmpty()) + continue; + + (*it)->setAttribute(HTMLNames::alignAttr, alignmentValue); + } +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLTableElement.h b/Source/WebCore/wml/WMLTableElement.h new file mode 100644 index 0000000..9f0a592 --- /dev/null +++ b/Source/WebCore/wml/WMLTableElement.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLTableElement_h +#define WMLTableElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +namespace WebCore { + +class HTMLCollection; + +class WMLTableElement : public WMLElement { +public: + static PassRefPtr<WMLTableElement> create(const QualifiedName&, Document*); + + WMLTableElement(const QualifiedName& tagName, Document*); + virtual ~WMLTableElement(); + + virtual bool mapToEntry(const QualifiedName&, MappedAttributeEntry&) const; + virtual void parseMappedAttribute(Attribute*); + + virtual void finishParsingChildren(); + +private: + Vector<WMLElement*> scanTableChildElements(WMLElement* startElement, const QualifiedName& tagName) const; + + bool tryMergeAdjacentTextCells(Node* item, Node* nextItem) const; + void transferAllChildrenOfElementToTargetElement(WMLElement* sourceElement, WMLElement* targetElement, unsigned startOffset) const; + void joinSuperflousColumns(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const; + void padWithEmptyColumns(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const; + void alignCells(Vector<WMLElement*>& columnElements, WMLElement* rowElement) const; + + unsigned m_columns; + String m_alignment; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLTagNames.in b/Source/WebCore/wml/WMLTagNames.in new file mode 100644 index 0000000..fd7c762 --- /dev/null +++ b/Source/WebCore/wml/WMLTagNames.in @@ -0,0 +1,35 @@ +namespace="WML" +namespaceURI="http://www.wapforum.org/DTD/wml_1.1.xml" +guardFactoryWith="ENABLE(WML)" + +a +access +anchor +br interfaceName=WMLBRElement +card +do +fieldset interfaceName=WMLFieldSetElement +go +head interfaceName=WMLElement +img interfaceName=WMLImageElement +input +#if 0 +# Note: 'insertedLegend' is not an official WML element - internal purpose only! +#endif +insertedLegend interfaceName=WMLInsertedLegendElement +meta +noop +onevent interfaceName=WMLOnEventElement +optgroup interfaceName=WMLOptGroupElement +option +p +postfield +prev +refresh +select +setvar +table +td interfaceName=WMLElement +template +timer +tr interfaceName=WMLElement diff --git a/Source/WebCore/wml/WMLTaskElement.cpp b/Source/WebCore/wml/WMLTaskElement.cpp new file mode 100644 index 0000000..3d1d636 --- /dev/null +++ b/Source/WebCore/wml/WMLTaskElement.cpp @@ -0,0 +1,119 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLTaskElement.h" + +#include "WMLAnchorElement.h" +#include "WMLDoElement.h" +#include "WMLNames.h" +#include "WMLOnEventElement.h" +#include "WMLPageState.h" +#include "WMLSetvarElement.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLTaskElement::WMLTaskElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +WMLTaskElement::~WMLTaskElement() +{ +} + +void WMLTaskElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + ContainerNode* parent = parentNode(); + if (!parent || !parent->isWMLElement()) + return; + + if (parent->hasTagName(anchorTag)) + static_cast<WMLAnchorElement*>(parent)->registerTask(this); + else if (parent->hasTagName(doTag)) + static_cast<WMLDoElement*>(parent)->registerTask(this); + else if (parent->hasTagName(oneventTag)) + static_cast<WMLOnEventElement*>(parent)->registerTask(this); +} + +void WMLTaskElement::removedFromDocument() +{ + ContainerNode* parent = parentNode(); + if (parent && parent->isWMLElement()) { + if (parent->hasTagName(anchorTag)) + static_cast<WMLAnchorElement*>(parent)->deregisterTask(this); + else if (parent->hasTagName(doTag)) + static_cast<WMLDoElement*>(parent)->deregisterTask(this); + else if (parent->hasTagName(oneventTag)) + static_cast<WMLOnEventElement*>(parent)->deregisterTask(this); + } + + WMLElement::removedFromDocument(); +} + +void WMLTaskElement::registerVariableSetter(WMLSetvarElement* element) +{ + ASSERT(m_variableSetterElements.find(element) == WTF::notFound); + m_variableSetterElements.append(element); +} + +void WMLTaskElement::deregisterVariableSetter(WMLSetvarElement* element) +{ + size_t position = m_variableSetterElements.find(element); + ASSERT(position != WTF::notFound); + m_variableSetterElements.remove(position); +} + +void WMLTaskElement::storeVariableState(WMLPageState* pageState) +{ + if (!pageState || m_variableSetterElements.isEmpty()) + return; + + WMLVariableMap variables; + Vector<WMLSetvarElement*>::iterator it = m_variableSetterElements.begin(); + Vector<WMLSetvarElement*>::iterator end = m_variableSetterElements.end(); + + for (; it != end; ++it) { + WMLSetvarElement* setterElement = (*it); + + String name = setterElement->name(); + if (name.isEmpty()) + continue; + + String value = setterElement->value(); + variables.set(name, value); + + // The next setvar element may depend on this variable value. It's safe to store the current + // name value pair in the page state, as the whole page state is replaced soon by this new map + pageState->storeVariable(name, value); + } + + pageState->storeVariables(variables); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLTaskElement.h b/Source/WebCore/wml/WMLTaskElement.h new file mode 100644 index 0000000..91e2a32 --- /dev/null +++ b/Source/WebCore/wml/WMLTaskElement.h @@ -0,0 +1,58 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLTaskElement_h +#define WMLTaskElement_h + +#if ENABLE(WML) +#include "WMLElement.h" + +#include <wtf/Vector.h> + +namespace WebCore { + +class WMLPageState; +class WMLSetvarElement; + +class WMLTaskElement : public WMLElement { +public: + virtual bool isWMLTaskElement() const { return true; } + + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + virtual void executeTask() = 0; + + void registerVariableSetter(WMLSetvarElement*); + void deregisterVariableSetter(WMLSetvarElement*); + +protected: + WMLTaskElement(const QualifiedName& tagName, Document*); + virtual ~WMLTaskElement(); + + void storeVariableState(WMLPageState*); + +private: + Vector<WMLSetvarElement*> m_variableSetterElements; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLTemplateElement.cpp b/Source/WebCore/wml/WMLTemplateElement.cpp new file mode 100644 index 0000000..584a762 --- /dev/null +++ b/Source/WebCore/wml/WMLTemplateElement.cpp @@ -0,0 +1,120 @@ +/* + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLTemplateElement.h" + +#include "Attribute.h" +#include "NodeList.h" +#include "WMLCardElement.h" +#include "WMLDocument.h" +#include "WMLIntrinsicEventHandler.h" +#include "WMLNames.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLTemplateElement::WMLTemplateElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) +{ +} + +WMLTemplateElement::~WMLTemplateElement() +{ +} + +PassRefPtr<WMLTemplateElement> WMLTemplateElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLTemplateElement(tagName, document)); +} + +void WMLTemplateElement::parseMappedAttribute(Attribute* attr) +{ + WMLIntrinsicEventType eventType = WMLIntrinsicEventUnknown; + + if (attr->name() == onenterforwardAttr) + eventType = WMLIntrinsicEventOnEnterForward; + else if (attr->name() == onenterbackwardAttr) + eventType = WMLIntrinsicEventOnEnterBackward; + else if (attr->name() == ontimerAttr) + eventType = WMLIntrinsicEventOnTimer; + else { + WMLElement::parseMappedAttribute(attr); + return; + } + + if (eventType == WMLIntrinsicEventUnknown) + return; + + // Register intrinsic event in card + RefPtr<WMLIntrinsicEvent> event = WMLIntrinsicEvent::create(document(), attr->value()); + + createEventHandlerIfNeeded(); + eventHandler()->registerIntrinsicEvent(eventType, event); +} + +void WMLTemplateElement::registerTemplatesInDocument(Document* doc) +{ + ASSERT(doc); + + // Build list of cards in document + RefPtr<NodeList> nodeList = doc->getElementsByTagName("card"); + if (!nodeList) + return; + + unsigned length = nodeList->length(); + if (length < 1) + return; + + HashSet<WMLCardElement*> cards; + for (unsigned i = 0; i < length; ++i) + cards.add(static_cast<WMLCardElement*>(nodeList->item(i))); + + if (cards.isEmpty()) + return; + + // Register template element to all cards + nodeList = doc->getElementsByTagName("template"); + if (!nodeList) + return; + + length = nodeList->length(); + if (length < 1) + return; + + // Only one template element should be allowed in a document + // Calling setTemplateElement() twice on a WMLCardElement, will result in a parser error. + for (unsigned i = 0; i < length; ++i) { + WMLTemplateElement* temp = static_cast<WMLTemplateElement*>(nodeList->item(i)); + + HashSet<WMLCardElement*>::iterator it = cards.begin(); + HashSet<WMLCardElement*>::iterator end = cards.end(); + + for (; it != end; ++it) + (*it)->setTemplateElement(temp); + } +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLTemplateElement.h b/Source/WebCore/wml/WMLTemplateElement.h new file mode 100644 index 0000000..c168753 --- /dev/null +++ b/Source/WebCore/wml/WMLTemplateElement.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2008, 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLTemplateElement_h +#define WMLTemplateElement_h + +#if ENABLE(WML) +#include "WMLElement.h" +#include "WMLEventHandlingElement.h" + +namespace WebCore { + +class WMLTemplateElement : public WMLElement, public WMLEventHandlingElement { +public: + static PassRefPtr<WMLTemplateElement> create(const QualifiedName&, Document*); + + WMLTemplateElement(const QualifiedName&, Document*); + virtual ~WMLTemplateElement(); + + virtual void parseMappedAttribute(Attribute*); + + static void registerTemplatesInDocument(Document*); +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLTimerElement.cpp b/Source/WebCore/wml/WMLTimerElement.cpp new file mode 100644 index 0000000..dd6c4aa --- /dev/null +++ b/Source/WebCore/wml/WMLTimerElement.cpp @@ -0,0 +1,161 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLTimerElement.h" + +#include "Attribute.h" +#include "HTMLNames.h" +#include "WMLCardElement.h" +#include "WMLDocument.h" +#include "WMLNames.h" +#include "WMLPageState.h" +#include "WMLTemplateElement.h" +#include "WMLVariables.h" + +namespace WebCore { + +using namespace WMLNames; + +WMLTimerElement::WMLTimerElement(const QualifiedName& tagName, Document* doc) + : WMLElement(tagName, doc) + , m_timer(this, &WMLTimerElement::timerFired) +{ +} + +PassRefPtr<WMLTimerElement> WMLTimerElement::create(const QualifiedName& tagName, Document* document) +{ + return adoptRef(new WMLTimerElement(tagName, document)); +} + +void WMLTimerElement::parseMappedAttribute(Attribute* attr) +{ + if (attr->name() == HTMLNames::nameAttr) + m_name = parseValueForbiddingVariableReferences(attr->value()); + else + WMLElement::parseMappedAttribute(attr); +} + +void WMLTimerElement::insertedIntoDocument() +{ + WMLElement::insertedIntoDocument(); + + // If the value of timeout is not a positive integer, ignore it + if (value().toInt() <= 0) + return; + + ContainerNode* parent = parentNode(); + if (!parent || !parent->isWMLElement()) + return; + + if (parent->hasTagName(cardTag)) { + m_card = static_cast<WMLCardElement*>(parent); + m_card->setIntrinsicEventTimer(this); + } +} + +void WMLTimerElement::removedFromDocument() +{ + ContainerNode* parent = parentNode(); + if (parent && parent->isWMLElement() && parent->hasTagName(cardTag)) { + m_card->setIntrinsicEventTimer(0); + m_card = 0; + } + + WMLElement::removedFromDocument(); +} + +void WMLTimerElement::timerFired(Timer<WMLTimerElement>*) +{ + if (!m_card) + return; + + WMLPageState* pageState = wmlPageStateForDocument(document()); + if (!pageState) + return; + + String value = this->value(); + + // When the timer expires, set the name varialbe of timer to '0' + if (!m_name.isEmpty()) { + value = "0"; + pageState->storeVariable(m_name, value); + } + + WMLIntrinsicEventType eventType = WMLIntrinsicEventOnTimer; + WMLIntrinsicEventHandler* eventHandler = m_card->eventHandler(); + + bool hasIntrinsicEvent = false; + if (eventHandler && eventHandler->hasIntrinsicEvent(eventType)) + hasIntrinsicEvent = true; + else if (m_card->templateElement()) { + eventHandler = m_card->templateElement()->eventHandler(); + if (eventHandler && eventHandler->hasIntrinsicEvent(eventType)) + hasIntrinsicEvent = true; + } + + if (hasIntrinsicEvent) + eventHandler->triggerIntrinsicEvent(eventType); +} + +void WMLTimerElement::start(int interval) +{ + if (!m_card || m_timer.isActive()) + return; + + if (interval <= 0 && !m_name.isEmpty()) { + if (WMLPageState* pageState = wmlPageStateForDocument(document())) + interval = pageState->getVariable(m_name).toInt(); + } + + if (interval <= 0) + interval = value().toInt(); + + if (interval > 0) + m_timer.startOneShot(interval / 10.0f); +} + +void WMLTimerElement::stop() +{ + if (m_timer.isActive()) + m_timer.stop(); +} + +void WMLTimerElement::storeIntervalToPageState() +{ + if (!m_timer.isActive()) + return; + + int interval = static_cast<int>(m_timer.nextFireInterval()) * 10; + + if (WMLPageState* pageState = wmlPageStateForDocument(document())) + pageState->storeVariable(m_name, String::number(interval)); +} + +String WMLTimerElement::value() const +{ + return parseValueSubstitutingVariableReferences(getAttribute(HTMLNames::valueAttr)); +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLTimerElement.h b/Source/WebCore/wml/WMLTimerElement.h new file mode 100644 index 0000000..894c793 --- /dev/null +++ b/Source/WebCore/wml/WMLTimerElement.h @@ -0,0 +1,59 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLTimerElement_h +#define WMLTimerElement_h + +#if ENABLE(WML) +#include "Timer.h" +#include "WMLElement.h" + +namespace WebCore { + +class WMLCardElement; + +class WMLTimerElement : public WMLElement { +public: + static PassRefPtr<WMLTimerElement> create(const QualifiedName&, Document*); + + WMLTimerElement(const QualifiedName& tagName, Document*); + + virtual void parseMappedAttribute(Attribute*); + virtual void insertedIntoDocument(); + virtual void removedFromDocument(); + + void timerFired(Timer<WMLTimerElement>*); + + void start(int interval = -1); + void stop(); + void storeIntervalToPageState(); + + String value() const; + +private: + WMLCardElement* m_card; + String m_name; + Timer<WMLTimerElement> m_timer; +}; + +} + +#endif +#endif diff --git a/Source/WebCore/wml/WMLVariables.cpp b/Source/WebCore/wml/WMLVariables.cpp new file mode 100644 index 0000000..f7be400 --- /dev/null +++ b/Source/WebCore/wml/WMLVariables.cpp @@ -0,0 +1,286 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include "config.h" + +#if ENABLE(WML) +#include "WMLVariables.h" + +#include "WMLDocument.h" +#include <wtf/ASCIICType.h> + +namespace WebCore { + +// WML variables specification, excluding the +// pre-WML 1.0 deprecated variable syntax +// +// varname = ("_" | alpha) ("_" | alpha | digit)* +// conv = ":" ("e" ("scape")? | "n" ("oesc")? | "u" ("nesc")?) +// var = ("$" varname) | ("$(" varname (conv)? ")") + +static bool isValidFirstVariableNameCharacter(const UChar& character) +{ + return WTF::isASCIIAlpha(character) + || character == '_'; +} + +static bool isValidVariableNameCharacter(const UChar& character) +{ + return WTF::isASCIIAlpha(character) + || WTF::isASCIIDigit(character) + || character == '_'; +} + +static bool isValidVariableEscapingModeString(const String& mode, WMLVariableEscapingMode& escapeMode) +{ + if (mode == "e" || mode == "escape") + escapeMode = WMLVariableEscapingEscape; + else if (mode == "u" || mode == "unesc") + escapeMode = WMLVariableEscapingUnescape; + else if (mode == "n" || mode == "noesc") + escapeMode = WMLVariableEscapingNone; + else + return false; + + return true; +} + +bool isValidVariableName(const String& name) +{ + if (name.isEmpty()) + return false; + + const UChar* characters = name.characters(); + if (!isValidFirstVariableNameCharacter(characters[0])) + return false; + + unsigned length = name.length(); + for (unsigned i = 1; i < length; ++i) { + if (!isValidVariableNameCharacter(characters[i])) + return false; + } + + return true; +} + +bool containsVariableReference(const String& text, bool& isValid) +{ + isValid = true; + bool foundReference = false; + bool finished = false; + int currentPosition = 0; + const UChar* characters = text.characters(); + + while (!finished) { + // Find beginning of variable reference + int referenceStartPosition = text.find('$', currentPosition); + if (referenceStartPosition == -1) { + finished = true; + break; + } + + foundReference = true; + + int nameStartPosition = referenceStartPosition + 1; + int nameEndPosition = -1; + + if (characters[nameStartPosition] == '(') { + // If the input string contains an open brace, a close brace must exist as well + nameEndPosition = text.find(')', nameStartPosition + 1); + if (nameEndPosition == -1) { + finished = true; + isValid = false; + break; + } + + ++nameStartPosition; + } else { + int length = text.length(); + for (nameEndPosition = nameStartPosition; nameEndPosition < length; ++nameEndPosition) { + if (!isValidVariableNameCharacter(text[nameEndPosition])) + break; + } + } + + if (nameEndPosition < nameStartPosition) { + finished = true; + isValid = false; + break; + } + + // Eventually split of conversion string, and check its syntax afterwards + String conversionString; + String variableName = text.substring(nameStartPosition, nameEndPosition - nameStartPosition); + + int conversionStringStart = variableName.find(':'); + if (conversionStringStart != -1) { + conversionString = variableName.substring(conversionStringStart + 1, variableName.length() - (conversionStringStart + 1)); + variableName = variableName.left(conversionStringStart); + } + + isValid = isValidVariableName(variableName); + if (!isValid) { + finished = true; + break; + } + + if (!conversionString.isEmpty()) { + isValid = isValidVariableName(conversionString); + if (!isValid) { + finished = true; + break; + } + + WMLVariableEscapingMode escapeMode = WMLVariableEscapingNone; + isValid = isValidVariableEscapingModeString(conversionString, escapeMode); + if (!isValid) { + finished = true; + break; + } + } + + currentPosition = nameEndPosition; + } + + return foundReference; +} + +String substituteVariableReferences(const String& reference, Document* document, WMLVariableEscapingMode escapeMode) +{ + ASSERT(document); + + if (reference.isEmpty()) + return reference; + + WMLPageState* pageState = wmlPageStateForDocument(document); + if (!pageState) + return reference; + + bool isValid = true; + String remainingInput = reference; + String result; + + while (!remainingInput.isEmpty()) { + ASSERT(isValid); + + int start = remainingInput.find("$"); + if (start == -1) { + // Consume all remaining characters, as there's nothing more to substitute + result += remainingInput; + break; + } + + // Consume all characters until the variable reference beginning + result += remainingInput.left(start); + remainingInput.remove(0, start); + + // Transform adjacent dollar signs into a single dollar sign as string literal + if (remainingInput[1] == '$') { + result += "$"; + remainingInput.remove(0, 2); + continue; + } + + String variableName; + String conversionMode; + + if (remainingInput[1] == '(') { + int referenceEndPosition = remainingInput.find(")"); + if (referenceEndPosition == -1) { + isValid = false; + break; + } + + variableName = remainingInput.substring(2, referenceEndPosition - 2); + remainingInput.remove(0, referenceEndPosition + 1); + + // Determine variable conversion mode string + int pos = variableName.find(':'); + if (pos != -1) { + conversionMode = variableName.substring(pos + 1, variableName.length() - (pos + 1)); + variableName = variableName.left(pos); + } + } else { + int length = remainingInput.length(); + int referenceEndPosition = 1; + + for (; referenceEndPosition < length; ++referenceEndPosition) { + if (!isValidVariableNameCharacter(remainingInput[referenceEndPosition])) + break; + } + + variableName = remainingInput.substring(1, referenceEndPosition - 1); + remainingInput.remove(0, referenceEndPosition); + } + + isValid = isValidVariableName(variableName); + if (!isValid) + break; + + ASSERT(!variableName.isEmpty()); + + String variableValue = pageState->getVariable(variableName); + if (variableValue.isEmpty()) + continue; + + if (containsVariableReference(variableValue, isValid)) { + if (!isValid) + break; + + variableValue = substituteVariableReferences(variableValue, document, escapeMode); + continue; + } + + if (!conversionMode.isEmpty()) { + // Override default escape mode, if desired + WMLVariableEscapingMode specifiedEscapeMode = WMLVariableEscapingNone; + if ((isValid = isValidVariableEscapingModeString(conversionMode, specifiedEscapeMode))) + escapeMode = specifiedEscapeMode; + + if (!isValid) + break; + } + + switch (escapeMode) { + case WMLVariableEscapingNone: + break; + case WMLVariableEscapingEscape: + variableValue = encodeWithURLEscapeSequences(variableValue); + break; + case WMLVariableEscapingUnescape: + variableValue = decodeURLEscapeSequences(variableValue); + break; + } + + result += variableValue; + ASSERT(isValid); + } + + if (!isValid) { + reportWMLError(document, WMLErrorInvalidVariableReference); + return reference; + } + + return result; +} + +} + +#endif diff --git a/Source/WebCore/wml/WMLVariables.h b/Source/WebCore/wml/WMLVariables.h new file mode 100644 index 0000000..3bd0f81 --- /dev/null +++ b/Source/WebCore/wml/WMLVariables.h @@ -0,0 +1,47 @@ +/** + * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifndef WMLVariables_h +#define WMLVariables_h + +#include <wtf/Forward.h> + +#if ENABLE(WML) +namespace WebCore { + + class Document; + + enum WMLVariableEscapingMode { + WMLVariableEscapingNone = 0, + WMLVariableEscapingEscape, + WMLVariableEscapingUnescape + }; + + bool isValidVariableName(const String&); + bool containsVariableReference(const String&, bool& isValid); + + String substituteVariableReferences(const String& variableReference, + Document*, + WMLVariableEscapingMode mode = WMLVariableEscapingNone); + +} + +#endif +#endif |