https://bugs.webkit.org/show_bug.cgi?id=120506
Reviewed by Darin Adler.
Encapsulate the conversion between VisiblePosition and index into indexForVisiblePosition
and visiblePositionForIndexUsingCharacterIterator. It's unfortunate that these two functions
are different from the two other existing functions of similar names but we've at least
confined problems into a single cpp file now.
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::visiblePositionForIndex):
(WebCore::AccessibilityRenderObject::indexForVisiblePosition):
* editing/Editor.cpp:
(WebCore::findFirstMarkable):
* editing/htmlediting.cpp:
(WebCore::indexForVisiblePosition):
(WebCore::visiblePositionForIndexUsingCharacterIterator):
* editing/htmlediting.h:
* html/HTMLTextFormControlElement.cpp:
(WebCore::hasVisibleTextArea):
(WebCore::HTMLTextFormControlElement::setSelectionRange):
(WebCore::HTMLTextFormControlElement::indexForVisiblePosition):
(WebCore::HTMLTextFormControlElement::visiblePositionForIndex):
* html/HTMLTextFormControlElement.h:
* rendering/RenderTextControl.cpp:
* rendering/RenderTextControl.h:
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@154868
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2013-08-29 Ryosuke Niwa <rniwa@webkit.org>
+
+ Unduplicate the code to convert between VisiblePosition and index
+ https://bugs.webkit.org/show_bug.cgi?id=120506
+
+ Reviewed by Darin Adler.
+
+ Encapsulate the conversion between VisiblePosition and index into indexForVisiblePosition
+ and visiblePositionForIndexUsingCharacterIterator. It's unfortunate that these two functions
+ are different from the two other existing functions of similar names but we've at least
+ confined problems into a single cpp file now.
+
+ * accessibility/AccessibilityRenderObject.cpp:
+ (WebCore::AccessibilityRenderObject::visiblePositionForIndex):
+ (WebCore::AccessibilityRenderObject::indexForVisiblePosition):
+ * editing/Editor.cpp:
+ (WebCore::findFirstMarkable):
+ * editing/htmlediting.cpp:
+ (WebCore::indexForVisiblePosition):
+ (WebCore::visiblePositionForIndexUsingCharacterIterator):
+ * editing/htmlediting.h:
+ * html/HTMLTextFormControlElement.cpp:
+ (WebCore::hasVisibleTextArea):
+ (WebCore::HTMLTextFormControlElement::setSelectionRange):
+ (WebCore::HTMLTextFormControlElement::indexForVisiblePosition):
+ (WebCore::HTMLTextFormControlElement::visiblePositionForIndex):
+ * html/HTMLTextFormControlElement.h:
+ * rendering/RenderTextControl.cpp:
+ * rendering/RenderTextControl.h:
+
2013-08-29 Ryosuke Niwa <rniwa@webkit.org>
Avoid Node references from AXObjectCache from leaking
{
if (!m_renderer)
return VisiblePosition();
-
+
if (isNativeTextControl())
- return toRenderTextControl(m_renderer)->visiblePositionForIndex(index);
+ return toRenderTextControl(m_renderer)->textFormControlElement()->visiblePositionForIndex(index);
if (!allowsTextRanges() && !m_renderer->isText())
return VisiblePosition();
Node* node = m_renderer->node();
if (!node)
return VisiblePosition();
-
- if (index <= 0)
- return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
-
- RefPtr<Range> range = Range::create(&m_renderer->document());
- range->selectNodeContents(node, IGNORE_EXCEPTION);
- CharacterIterator it(range.get());
- it.advance(index - 1);
- return VisiblePosition(Position(it.range()->endContainer(), it.range()->endOffset(), Position::PositionIsOffsetInAnchor), UPSTREAM);
+
+ return visiblePositionForIndexUsingCharacterIterator(node, index);
}
int AccessibilityRenderObject::indexForVisiblePosition(const VisiblePosition& pos) const
{
- if (isNativeTextControl()) {
- HTMLTextFormControlElement* textControl = toRenderTextControl(m_renderer)->textFormControlElement();
- return textControl->indexForVisiblePosition(pos);
- }
+ if (isNativeTextControl())
+ return toRenderTextControl(m_renderer)->textFormControlElement()->indexForVisiblePosition(pos);
if (!isTextControl())
return 0;
Node* node = m_renderer->node();
if (!node)
return 0;
-
+
Position indexPosition = pos.deepEquivalent();
if (indexPosition.isNull() || highestEditableRoot(indexPosition, HasEditableAXRole) != node)
return 0;
-
- RefPtr<Range> range = Range::create(&m_renderer->document());
- range->setStart(node, 0, IGNORE_EXCEPTION);
- range->setEnd(indexPosition, IGNORE_EXCEPTION);
#if PLATFORM(GTK)
// We need to consider replaced elements for GTK, as they will be
// presented with the 'object replacement character' (0xFFFC).
- return TextIterator::rangeLength(range.get(), true);
+ bool forSelectionPreservation = true;
#else
- return TextIterator::rangeLength(range.get());
+ bool forSelectionPreservation = false;
#endif
+
+ return WebCore::indexForVisiblePosition(node, pos, forSelectionPreservation);
}
Element* AccessibilityRenderObject::rootEditableElementForPosition(const Position& position) const
return 0;
if (node->renderer()->isText())
return node;
- if (node->renderer()->isTextControl())
- node = toRenderTextControl(node->renderer())->visiblePositionForIndex(1).deepEquivalent().deprecatedNode();
+ if (isHTMLTextFormControlElement(node))
+ node = toHTMLTextFormControlElement(node)->visiblePositionForIndex(1).deepEquivalent().deprecatedNode();
else if (node->firstChild())
node = node->firstChild();
else
return TextIterator::rangeLength(range.get(), true);
}
+// FIXME: Merge these two functions.
+int indexForVisiblePosition(Node* node, const VisiblePosition& visiblePosition, bool forSelectionPreservation)
+{
+ ASSERT(node);
+ RefPtr<Range> range = Range::create(node->document(), firstPositionInNode(node), visiblePosition.deepEquivalent().parentAnchoredEquivalent());
+ return TextIterator::rangeLength(range.get(), forSelectionPreservation);
+}
+
VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope)
{
RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(scope, index, 0, true);
return VisiblePosition(range->startPosition());
}
+VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node* node, int index)
+{
+ ASSERT(node);
+ if (index <= 0)
+ return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
+
+ RefPtr<Range> range = Range::create(node->document());
+ range->selectNodeContents(node, IGNORE_EXCEPTION);
+ CharacterIterator it(range.get());
+ it.advance(index - 1);
+
+ return VisiblePosition(Position(it.range()->endContainer(), it.range()->endOffset(), Position::PositionIsOffsetInAnchor), UPSTREAM);
+}
+
// Determines whether two positions are visibly next to each other (first then second)
// while ignoring whitespaces and unrendered nodes
bool isVisiblyAdjacent(const Position& first, const Position& second)
int comparePositions(const VisiblePosition&, const VisiblePosition&);
int indexForVisiblePosition(const VisiblePosition&, RefPtr<ContainerNode>& scope);
+int indexForVisiblePosition(Node*, const VisiblePosition&, bool forSelectionPreservation);
VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope);
+VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node*, int index); // FIXME: Why do we need this version?
// -------------------------------------------------------------------------
// Range
#include "HTMLInputElement.h"
#include "HTMLNames.h"
#include "NodeTraversal.h"
-#include "RenderBox.h"
-#include "RenderTextControl.h"
+#include "RenderBlock.h"
#include "RenderTheme.h"
#include "ScriptEventListener.h"
#include "ShadowRoot.h"
#include "Text.h"
-#include "TextIterator.h"
+#include "htmlediting.h"
#include <wtf/text/StringBuilder.h>
namespace WebCore {
setChangedSinceLastFormControlChangeEvent(false);
}
-static inline bool hasVisibleTextArea(RenderTextControl* textControl, HTMLElement* innerText)
+static inline bool hasVisibleTextArea(RenderObject* textControl, HTMLElement* innerText)
{
ASSERT(textControl);
return textControl->style()->visibility() != HIDDEN && innerText && innerText->renderer() && innerText->renderBox()->height();
}
-
void HTMLTextFormControlElement::setRangeText(const String& replacement, ExceptionCode& ec)
{
setRangeText(replacement, selectionStart(), selectionEnd(), String(), ec);
end = max(end, 0);
start = min(max(start, 0), end);
- RenderTextControl* control = toRenderTextControl(renderer());
- if (!hasVisibleTextArea(control, innerTextElement())) {
+ if (!hasVisibleTextArea(renderer(), innerTextElement())) {
cacheSelection(start, end, direction);
return;
}
- VisiblePosition startPosition = control->visiblePositionForIndex(start);
+ VisiblePosition startPosition = visiblePositionForIndex(start);
VisiblePosition endPosition;
if (start == end)
endPosition = startPosition;
else
- endPosition = control->visiblePositionForIndex(end);
+ endPosition = visiblePositionForIndex(end);
// startPosition and endPosition can be null position for example when
// "-webkit-user-select: none" style attribute is specified.
int HTMLTextFormControlElement::indexForVisiblePosition(const VisiblePosition& pos) const
{
- Position indexPosition = pos.deepEquivalent().parentAnchoredEquivalent();
- if (enclosingTextFormControl(indexPosition) != this)
+ if (enclosingTextFormControl(pos.deepEquivalent()) != this)
return 0;
- RefPtr<Range> range = Range::create(indexPosition.document());
- range->setStart(innerTextElement(), 0, ASSERT_NO_EXCEPTION);
- range->setEnd(indexPosition.containerNode(), indexPosition.offsetInContainerNode(), ASSERT_NO_EXCEPTION);
- return TextIterator::rangeLength(range.get());
+ bool forSelectionPreservation = false;
+ return WebCore::indexForVisiblePosition(innerTextElement(), pos, forSelectionPreservation);
+}
+
+VisiblePosition HTMLTextFormControlElement::visiblePositionForIndex(int index) const
+{
+ return visiblePositionForIndexUsingCharacterIterator(innerTextElement(), index);
}
int HTMLTextFormControlElement::selectionStart() const
static void fixPlaceholderRenderer(HTMLElement* placeholder, HTMLElement* siblingElement);
int indexForVisiblePosition(const VisiblePosition&) const;
+ VisiblePosition visiblePositionForIndex(int index) const;
int selectionStart() const;
int selectionEnd() const;
const AtomicString& selectionDirection() const;
updateUserModifyProperty(node(), innerText->renderer()->style());
}
-VisiblePosition RenderTextControl::visiblePositionForIndex(int index) const
-{
- if (index <= 0)
- return VisiblePosition(firstPositionInNode(innerTextElement()), DOWNSTREAM);
- RefPtr<Range> range = Range::create(&document());
- range->selectNodeContents(innerTextElement(), ASSERT_NO_EXCEPTION);
- CharacterIterator it(range.get());
- it.advance(index - 1);
- return VisiblePosition(it.range()->endPosition(), UPSTREAM);
-}
-
int RenderTextControl::scrollbarThickness() const
{
// FIXME: We should get the size of the scrollbar from the RenderTheme instead.
HTMLTextFormControlElement* textFormControlElement() const;
virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
- VisiblePosition visiblePositionForIndex(int index) const;
-
protected:
RenderTextControl(Element*);