#include "config.h"
#include "core/editing/VisibleUnits.h"
-#include "HTMLNames.h"
-#include "RuntimeEnabledFeatures.h"
-#include "bindings/v8/ExceptionState.h"
-#include "bindings/v8/ExceptionStatePlaceholder.h"
+#include "bindings/core/v8/ExceptionState.h"
+#include "bindings/core/v8/ExceptionStatePlaceholder.h"
+#include "core/HTMLNames.h"
#include "core/dom/Document.h"
#include "core/dom/Element.h"
#include "core/dom/NodeTraversal.h"
#include "core/editing/TextIterator.h"
#include "core/editing/VisiblePosition.h"
#include "core/editing/htmlediting.h"
+#include "core/html/HTMLBRElement.h"
#include "core/rendering/InlineTextBox.h"
#include "core/rendering/RenderBlockFlow.h"
#include "core/rendering/RenderObject.h"
+#include "platform/RuntimeEnabledFeatures.h"
+#include "platform/heap/Handle.h"
#include "platform/text/TextBoundaries.h"
-namespace WebCore {
+namespace blink {
using namespace HTMLNames;
using namespace WTF::Unicode;
static Node* previousLeafWithSameEditability(Node* node, EditableType editableType)
{
- bool editable = node->rendererIsEditable(editableType);
+ bool editable = node->hasEditableStyle(editableType);
node = node->previousLeafNode();
while (node) {
- if (editable == node->rendererIsEditable(editableType))
+ if (editable == node->hasEditableStyle(editableType))
return node;
node = node->previousLeafNode();
}
if (!node)
return 0;
- bool editable = node->rendererIsEditable(editableType);
+ bool editable = node->hasEditableStyle(editableType);
node = node->nextLeafNode();
while (node) {
- if (editable == node->rendererIsEditable(editableType))
+ if (editable == node->hasEditableStyle(editableType))
return node;
node = node->nextLeafNode();
}
// FIXME: consolidate with code in previousLinePosition.
static Position previousRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
{
- Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
+ ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
Node* previousNode = previousLeafWithSameEditability(node, editableType);
- while (previousNode && (!previousNode->renderer() || inSameLine(firstPositionInOrBeforeNode(previousNode), visiblePosition)))
+ while (previousNode && (!previousNode->renderer() || inSameLine(VisiblePosition(firstPositionInOrBeforeNode(previousNode)), visiblePosition)))
previousNode = previousLeafWithSameEditability(previousNode, editableType);
while (previousNode && !previousNode->isShadowRoot()) {
if (highestEditableRoot(firstPositionInOrBeforeNode(previousNode), editableType) != highestRoot)
break;
- Position pos = previousNode->hasTagName(brTag) ? positionBeforeNode(previousNode) :
+ Position pos = isHTMLBRElement(*previousNode) ? positionBeforeNode(previousNode) :
createLegacyEditingPosition(previousNode, caretMaxOffset(previousNode));
if (pos.isCandidate())
static Position nextRootInlineBoxCandidatePosition(Node* node, const VisiblePosition& visiblePosition, EditableType editableType)
{
- Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
+ ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent(), editableType);
Node* nextNode = nextLeafWithSameEditability(node, editableType);
- while (nextNode && (!nextNode->renderer() || inSameLine(firstPositionInOrBeforeNode(nextNode), visiblePosition)))
+ while (nextNode && (!nextNode->renderer() || inSameLine(VisiblePosition(firstPositionInOrBeforeNode(nextNode)), visiblePosition)))
nextNode = nextLeafWithSameEditability(nextNode, ContentIsEditable);
while (nextNode && !nextNode->isShadowRoot()) {
{
const InlineBox* startBox = textBox;
- const InlineTextBox* previousBox = leafBoxes.previousTextBox(startBox->root(), textBox);
+ const InlineTextBox* previousBox = leafBoxes.previousTextBox(&startBox->root(), textBox);
if (previousBox)
return previousBox;
- previousBox = leafBoxes.previousTextBox(startBox->root()->prevRootBox(), 0);
+ previousBox = leafBoxes.previousTextBox(startBox->root().prevRootBox(), 0);
if (previousBox)
return previousBox;
while (1) {
- Node* startNode = startBox->renderer() ? startBox->renderer()->nonPseudoNode() : 0;
+ Node* startNode = startBox->renderer().nonPseudoNode();
if (!startNode)
break;
{
const InlineBox* startBox = textBox;
- const InlineTextBox* nextBox = leafBoxes.nextTextBox(startBox->root(), textBox);
+ const InlineTextBox* nextBox = leafBoxes.nextTextBox(&startBox->root(), textBox);
if (nextBox)
return nextBox;
- nextBox = leafBoxes.nextTextBox(startBox->root()->nextRootBox(), 0);
+ nextBox = leafBoxes.nextTextBox(startBox->root().nextRootBox(), 0);
if (nextBox)
return nextBox;
while (1) {
- Node* startNode = startBox->renderer() ? startBox->renderer()->nonPseudoNode() : 0;
+ Node* startNode =startBox->renderer().nonPseudoNode();
if (!startNode)
break;
string.clear();
if (previousBox) {
previousBoxLength = previousBox->len();
- previousBox->textRenderer()->text().appendTo(string, previousBox->start(), previousBoxLength);
+ previousBox->renderer().text().appendTo(string, previousBox->start(), previousBoxLength);
len += previousBoxLength;
}
- textBox->textRenderer()->text().appendTo(string, textBox->start(), textBox->len());
+ textBox->renderer().text().appendTo(string, textBox->start(), textBox->len());
len += textBox->len();
return wordBreakIterator(string.data(), len);
int len = 0;
string.clear();
- textBox->textRenderer()->text().appendTo(string, textBox->start(), textBox->len());
+ textBox->renderer().text().appendTo(string, textBox->start(), textBox->len());
len += textBox->len();
if (nextBox) {
- nextBox->textRenderer()->text().appendTo(string, nextBox->start(), nextBox->len());
+ nextBox->renderer().text().appendTo(string, nextBox->start(), nextBox->len());
len += nextBox->len();
}
else if (offsetInBox == box->caretMaxOffset())
iter = wordBreakIteratorForMaxOffsetBoundary(visiblePosition, textBox, nextBoxInDifferentBlock, string, leafBoxes);
else if (movingIntoNewBox) {
- iter = wordBreakIterator(textBox->textRenderer()->text(), textBox->start(), textBox->len());
+ iter = wordBreakIterator(textBox->renderer().text(), textBox->start(), textBox->len());
previouslyVisitedBox = box;
}
Document& d = boundary->document();
Position start = createLegacyEditingPosition(boundary, 0).parentAnchoredEquivalent();
Position end = pos.parentAnchoredEquivalent();
- RefPtr<Range> searchRange = Range::create(d);
+ RefPtrWillBeRawPtr<Range> searchRange = Range::create(d);
Vector<UChar, 1024> string;
unsigned suffixLength = 0;
TrackExceptionState exceptionState;
if (requiresContextForWordBoundary(c.characterBefore())) {
- RefPtr<Range> forwardsScanRange(d.createRange());
+ RefPtrWillBeRawPtr<Range> forwardsScanRange(d.createRange());
forwardsScanRange->setEndAfter(boundary, exceptionState);
forwardsScanRange->setStart(end.deprecatedNode(), end.deprecatedEditingOffset(), exceptionState);
TextIterator forwardsIterator(forwardsScanRange.get());
return VisiblePosition();
Document& d = boundary->document();
- RefPtr<Range> searchRange(d.createRange());
+ RefPtrWillBeRawPtr<Range> searchRange(d.createRange());
Position start(pos.parentAnchoredEquivalent());
Vector<UChar, 1024> string;
unsigned prefixLength = 0;
if (requiresContextForWordBoundary(c.characterAfter())) {
- RefPtr<Range> backwardsScanRange(d.createRange());
+ RefPtrWillBeRawPtr<Range> backwardsScanRange(d.createRange());
backwardsScanRange->setEnd(start.deprecatedNode(), start.deprecatedEditingOffset(), IGNORE_EXCEPTION);
SimplifiedBackwardsTextIterator backwardsIterator(backwardsScanRange.get());
while (!backwardsIterator.atEnd()) {
// Use the character iterator to translate the next value into a DOM position.
CharacterIterator charIt(searchRange.get(), TextIteratorEmitsCharactersBetweenAllVisiblePositions);
charIt.advance(next - prefixLength - 1);
- RefPtr<Range> characterRange = charIt.range();
+ RefPtrWillBeRawPtr<Range> characterRange = charIt.range();
pos = characterRange->endPosition();
if (charIt.characterAt(0) == '\n') {
return length;
}
needMoreContext = false;
- int start, end;
- findWordBoundary(characters, length, offset, &start, &end);
- return end;
+ return findWordEndBoundary(characters, length, offset);
}
VisiblePosition endOfWord(const VisiblePosition &c, EWordSide side)
if (!startBox)
return VisiblePosition();
- RenderObject* startRenderer = startBox->renderer();
- if (!startRenderer)
- return VisiblePosition();
-
- startNode = startRenderer->nonPseudoNode();
+ startNode = startBox->renderer().nonPseudoNode();
if (startNode)
break;
}
}
- return startNode->isTextNode() ? Position(toText(startNode), toInlineTextBox(startBox)->start())
- : positionBeforeNode(startNode);
+ return VisiblePosition(startNode->isTextNode() ? Position(toText(startNode), toInlineTextBox(startBox)->start()) : positionBeforeNode(startNode));
}
static VisiblePosition startOfLine(const VisiblePosition& c, LineEndpointComputationMode mode)
VisiblePosition visPos = startPositionForLine(c, mode);
if (mode == UseLogicalOrdering) {
- if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
+ if (ContainerNode* editableRoot = highestEditableRoot(c.deepEquivalent())) {
if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
- return firstPositionInNode(editableRoot);
+ return VisiblePosition(firstPositionInNode(editableRoot));
}
}
if (!endBox)
return VisiblePosition();
- RenderObject* endRenderer = endBox->renderer();
- if (!endRenderer)
- return VisiblePosition();
-
- endNode = endRenderer->nonPseudoNode();
+ endNode = endBox->renderer().nonPseudoNode();
if (endNode)
break;
}
Position pos;
- if (endNode->hasTagName(brTag))
+ if (isHTMLBRElement(*endNode))
pos = positionBeforeNode(endNode);
else if (endBox->isInlineTextBox() && endNode->isTextNode()) {
InlineTextBox* endTextBox = toInlineTextBox(endBox);
if (!inSameLogicalLine(c, visPos))
visPos = visPos.previous();
- if (Node* editableRoot = highestEditableRoot(c.deepEquivalent())) {
+ if (ContainerNode* editableRoot = highestEditableRoot(c.deepEquivalent())) {
if (!editableRoot->contains(visPos.deepEquivalent().containerNode()))
- return lastPositionInNode(editableRoot);
+ return VisiblePosition(lastPositionInNode(editableRoot));
}
return c.honorEditingBoundaryAtOrAfter(visPos);
return p.isNotNull() && p == endOfLine(p);
}
+bool isLogicalEndOfLine(const VisiblePosition &p)
+{
+ return p.isNotNull() && p == logicalEndOfLine(p);
+}
+
static inline IntPoint absoluteLineDirectionPointToLocalPointInBlock(RootInlineBox* root, int lineDirectionPoint)
{
ASSERT(root);
- RenderBlockFlow* containingBlock = root->block();
- FloatPoint absoluteBlockPoint = containingBlock->localToAbsolute(FloatPoint());
- if (containingBlock->hasOverflowClip())
- absoluteBlockPoint -= containingBlock->scrolledContentOffset();
+ RenderBlockFlow& containingBlock = root->block();
+ FloatPoint absoluteBlockPoint = containingBlock.localToAbsolute(FloatPoint());
+ if (containingBlock.hasOverflowClip())
+ absoluteBlockPoint -= containingBlock.scrolledContentOffset();
- if (root->block()->isHorizontalWritingMode())
+ if (root->block().isHorizontalWritingMode())
return IntPoint(lineDirectionPoint - absoluteBlockPoint.x(), root->blockDirectionPointInLine());
return IntPoint(root->blockDirectionPointInLine(), lineDirectionPoint - absoluteBlockPoint.y());
int ignoredCaretOffset;
visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
if (box) {
- root = box->root()->prevRootBox();
+ root = box->root().prevRootBox();
// We want to skip zero height boxes.
// This could happen in case it is a TrailingFloatsRootInlineBox.
if (!root || !root->logicalHeight() || !root->firstLeafChild())
if (!root) {
Position position = previousRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
if (position.isNotNull()) {
- RenderedPosition renderedPosition(position);
+ RenderedPosition renderedPosition((VisiblePosition(position)));
root = renderedPosition.rootBox();
if (!root)
- return position;
+ return VisiblePosition(position);
}
}
if (root) {
// FIXME: Can be wrong for multi-column layout and with transforms.
IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
- RenderObject* renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
- Node* node = renderer->node();
+ RenderObject& renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
+ Node* node = renderer.node();
if (node && editingIgnoresContent(node))
- return positionInParentBeforeNode(node);
- return VisiblePosition(renderer->positionForPoint(pointInLine));
+ return VisiblePosition(positionInParentBeforeNode(*node));
+ return VisiblePosition(renderer.positionForPoint(pointInLine));
}
// Could not find a previous line. This means we must already be on the first line.
// Move to the start of the content in this block, which effectively moves us
// to the start of the line we're on.
- Element* rootElement = node->rendererIsEditable(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
+ Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
if (!rootElement)
return VisiblePosition();
return VisiblePosition(firstPositionInNode(rootElement), DOWNSTREAM);
int ignoredCaretOffset;
visiblePosition.getInlineBoxAndOffset(box, ignoredCaretOffset);
if (box) {
- root = box->root()->nextRootBox();
+ root = box->root().nextRootBox();
// We want to skip zero height boxes.
// This could happen in case it is a TrailingFloatsRootInlineBox.
if (!root || !root->logicalHeight() || !root->firstLeafChild())
if (!root) {
// FIXME: We need do the same in previousLinePosition.
- Node* child = node->childNode(p.deprecatedEditingOffset());
- node = child ? child : &node->lastDescendant();
+ Node* child = NodeTraversal::childAt(*node, p.deprecatedEditingOffset());
+ node = child ? child : &NodeTraversal::lastWithinOrSelf(*node);
Position position = nextRootInlineBoxCandidatePosition(node, visiblePosition, editableType);
if (position.isNotNull()) {
- RenderedPosition renderedPosition(position);
+ RenderedPosition renderedPosition((VisiblePosition(position)));
root = renderedPosition.rootBox();
if (!root)
- return position;
+ return VisiblePosition(position);
}
}
if (root) {
// FIXME: Can be wrong for multi-column layout and with transforms.
IntPoint pointInLine = absoluteLineDirectionPointToLocalPointInBlock(root, lineDirectionPoint);
- RenderObject* renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
- Node* node = renderer->node();
+ RenderObject& renderer = root->closestLeafChildForPoint(pointInLine, isEditablePosition(p))->renderer();
+ Node* node = renderer.node();
if (node && editingIgnoresContent(node))
- return positionInParentBeforeNode(node);
- return VisiblePosition(renderer->positionForPoint(pointInLine));
+ return VisiblePosition(positionInParentBeforeNode(*node));
+ return VisiblePosition(renderer.positionForPoint(pointInLine));
}
// Could not find a next line. This means we must already be on the last line.
// Move to the end of the content in this block, which effectively moves us
// to the end of the line we're on.
- Element* rootElement = node->rendererIsEditable(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
+ Element* rootElement = node->hasEditableStyle(editableType) ? node->rootEditableElement(editableType) : node->document().documentElement();
if (!rootElement)
return VisiblePosition();
return VisiblePosition(lastPositionInNode(rootElement), DOWNSTREAM);
return VisiblePosition();
if (isRenderedAsNonInlineTableImageOrHR(startNode))
- return positionBeforeNode(startNode);
+ return VisiblePosition(positionBeforeNode(startNode));
- Node* startBlock = enclosingBlock(startNode);
+ Element* startBlock = enclosingBlock(startNode);
Node* node = startNode;
- Node* highestRoot = highestEditableRoot(p);
+ ContainerNode* highestRoot = highestEditableRoot(p);
int offset = p.deprecatedEditingOffset();
Position::AnchorType type = p.anchorType();
Node* n = startNode;
- bool startNodeIsEditable = startNode->rendererIsEditable();
+ bool startNodeIsEditable = startNode->hasEditableStyle();
while (n) {
- if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->rendererIsEditable() != startNodeIsEditable)
+ if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->hasEditableStyle() != startNodeIsEditable)
break;
if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
- while (n && n->rendererIsEditable() != startNodeIsEditable)
+ while (n && n->hasEditableStyle() != startNodeIsEditable)
n = NodeTraversal::previousPostOrder(*n, startBlock);
if (!n || !n->isDescendantOf(highestRoot))
break;
node = n;
offset = 0;
n = NodeTraversal::previousPostOrder(*n, startBlock);
- } else if (editingIgnoresContent(n) || isRenderedTable(n)) {
+ } else if (editingIgnoresContent(n) || isRenderedTableElement(n)) {
node = n;
type = Position::PositionIsBeforeAnchor;
n = n->previousSibling() ? n->previousSibling() : NodeTraversal::previousPostOrder(*n, startBlock);
Node* startNode = p.deprecatedNode();
if (isRenderedAsNonInlineTableImageOrHR(startNode))
- return positionAfterNode(startNode);
+ return VisiblePosition(positionAfterNode(startNode));
- Node* startBlock = enclosingBlock(startNode);
- Node* stayInsideBlock = startBlock;
+ Element* startBlock = enclosingBlock(startNode);
+ Element* stayInsideBlock = startBlock;
Node* node = startNode;
- Node* highestRoot = highestEditableRoot(p);
+ ContainerNode* highestRoot = highestEditableRoot(p);
int offset = p.deprecatedEditingOffset();
Position::AnchorType type = p.anchorType();
Node* n = startNode;
- bool startNodeIsEditable = startNode->rendererIsEditable();
+ bool startNodeIsEditable = startNode->hasEditableStyle();
while (n) {
- if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->rendererIsEditable() != startNodeIsEditable)
+ if (boundaryCrossingRule == CannotCrossEditingBoundary && !Position::nodeIsUserSelectAll(n) && n->hasEditableStyle() != startNodeIsEditable)
break;
if (boundaryCrossingRule == CanSkipOverEditingBoundary) {
- while (n && n->rendererIsEditable() != startNodeIsEditable)
+ while (n && n->hasEditableStyle() != startNodeIsEditable)
n = NodeTraversal::next(*n, stayInsideBlock);
if (!n || !n->isDescendantOf(highestRoot))
break;
node = n;
offset = r->caretMaxOffset();
n = NodeTraversal::next(*n, stayInsideBlock);
- } else if (editingIgnoresContent(n) || isRenderedTable(n)) {
+ } else if (editingIgnoresContent(n) || isRenderedTableElement(n)) {
node = n;
type = Position::PositionIsAfterAnchor;
n = NodeTraversal::nextSkippingChildren(*n, stayInsideBlock);
VisiblePosition startOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
{
Position position = visiblePosition.deepEquivalent();
- Node* startBlock;
- if (!position.containerNode() || !(startBlock = enclosingBlock(position.containerNode(), rule)))
- return VisiblePosition();
- return firstPositionInNode(startBlock);
+ Element* startBlock = position.containerNode() ? enclosingBlock(position.containerNode(), rule) : 0;
+ return startBlock ? VisiblePosition(firstPositionInNode(startBlock)) : VisiblePosition();
}
VisiblePosition endOfBlock(const VisiblePosition& visiblePosition, EditingBoundaryCrossingRule rule)
{
Position position = visiblePosition.deepEquivalent();
- Node* endBlock;
- if (!position.containerNode() || !(endBlock = enclosingBlock(position.containerNode(), rule)))
- return VisiblePosition();
- return lastPositionInNode(endBlock);
+ Element* endBlock = position.containerNode() ? enclosingBlock(position.containerNode(), rule) : 0;
+ return endBlock ? VisiblePosition(lastPositionInNode(endBlock)) : VisiblePosition();
}
bool inSameBlock(const VisiblePosition &a, const VisiblePosition &b)
VisiblePosition startOfEditableContent(const VisiblePosition& visiblePosition)
{
- Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
+ ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
if (!highestRoot)
return VisiblePosition();
- return firstPositionInNode(highestRoot);
+ return VisiblePosition(firstPositionInNode(highestRoot));
}
VisiblePosition endOfEditableContent(const VisiblePosition& visiblePosition)
{
- Node* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
+ ContainerNode* highestRoot = highestEditableRoot(visiblePosition.deepEquivalent());
if (!highestRoot)
return VisiblePosition();
- return lastPositionInNode(highestRoot);
+ return VisiblePosition(lastPositionInNode(highestRoot));
}
bool isEndOfEditableOrNonEditableContent(const VisiblePosition &p)
return direction == LTR ? logicalEndOfLine(c) : logicalStartOfLine(c);
}
+LayoutRect localCaretRectOfPosition(const PositionWithAffinity& position, RenderObject*& renderer)
+{
+ if (position.position().isNull()) {
+ renderer = nullptr;
+ return IntRect();
+ }
+ Node* node = position.position().anchorNode();
+
+ renderer = node->renderer();
+ if (!renderer)
+ return LayoutRect();
+
+ InlineBox* inlineBox;
+ int caretOffset;
+ position.position().getInlineBoxAndOffset(position.affinity(), inlineBox, caretOffset);
+
+ if (inlineBox)
+ renderer = &inlineBox->renderer();
+
+ return renderer->localCaretRect(inlineBox, caretOffset);
+}
+
}