| Index: Source/core/editing/htmlediting.cpp
|
| diff --git a/Source/core/editing/htmlediting.cpp b/Source/core/editing/htmlediting.cpp
|
| index c00896fc9dee7f2939f77dce27cae1896c6d2b24..756ee454b249255888de4db3c30eabdac2189af1 100644
|
| --- a/Source/core/editing/htmlediting.cpp
|
| +++ b/Source/core/editing/htmlediting.cpp
|
| @@ -20,7 +20,7 @@
|
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
|
| * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
| - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
| */
|
|
|
| #include "config.h"
|
| @@ -109,11 +109,11 @@ Node* highestEditableRoot(const Position& position, EditableType editableType)
|
| Node* node = position.deprecatedNode();
|
| if (!node)
|
| return 0;
|
| -
|
| +
|
| Node* highestRoot = editableRootForPosition(position, editableType);
|
| if (!highestRoot)
|
| return 0;
|
| -
|
| +
|
| node = highestRoot;
|
| while (node) {
|
| if (node->rendererIsEditable(editableType))
|
| @@ -122,7 +122,7 @@ Node* highestEditableRoot(const Position& position, EditableType editableType)
|
| break;
|
| node = node->parentNode();
|
| }
|
| -
|
| +
|
| return highestRoot;
|
| }
|
|
|
| @@ -130,7 +130,7 @@ Node* lowestEditableAncestor(Node* node)
|
| {
|
| if (!node)
|
| return 0;
|
| -
|
| +
|
| Node* lowestRoot = 0;
|
| while (node) {
|
| if (node->rendererIsEditable())
|
| @@ -139,7 +139,7 @@ Node* lowestEditableAncestor(Node* node)
|
| break;
|
| node = node->parentNode();
|
| }
|
| -
|
| +
|
| return lowestRoot;
|
| }
|
|
|
| @@ -155,7 +155,7 @@ bool isEditablePosition(const Position& p, EditableType editableType, EUpdateSty
|
|
|
| if (node->renderer() && node->renderer()->isTable())
|
| node = node->parentNode();
|
| -
|
| +
|
| return node->rendererIsEditable(editableType);
|
| }
|
|
|
| @@ -164,17 +164,17 @@ bool isAtUnsplittableElement(const Position& pos)
|
| Node* node = pos.deprecatedNode();
|
| return (node == editableRootForPosition(pos) || node == enclosingNodeOfType(pos, &isTableCell));
|
| }
|
| -
|
| -
|
| +
|
| +
|
| bool isRichlyEditablePosition(const Position& p, EditableType editableType)
|
| {
|
| Node* node = p.deprecatedNode();
|
| if (!node)
|
| return false;
|
| -
|
| +
|
| if (node->renderer() && node->renderer()->isTable())
|
| node = node->parentNode();
|
| -
|
| +
|
| return node->rendererIsRichlyEditable(editableType);
|
| }
|
|
|
| @@ -183,10 +183,10 @@ Element* editableRootForPosition(const Position& p, EditableType editableType)
|
| Node* node = p.containerNode();
|
| if (!node)
|
| return 0;
|
| -
|
| +
|
| if (node->renderer() && node->renderer()->isTable())
|
| node = node->parentNode();
|
| -
|
| +
|
| return node->rootEditableElement(editableType);
|
| }
|
|
|
| @@ -268,10 +268,10 @@ VisiblePosition firstEditablePositionAfterPositionInRoot(const Position& positio
|
|
|
| while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->isDescendantOf(highestRoot))
|
| p = isAtomicNode(p.deprecatedNode()) ? positionInParentAfterNode(p.deprecatedNode()) : nextVisuallyDistinctCandidate(p);
|
| -
|
| +
|
| if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecatedNode()->isDescendantOf(highestRoot))
|
| return VisiblePosition();
|
| -
|
| +
|
| return VisiblePosition(p);
|
| }
|
|
|
| @@ -290,13 +290,13 @@ VisiblePosition lastEditablePositionBeforePositionInRoot(const Position& positio
|
|
|
| p = firstPositionInOrBeforeNode(shadowAncestor);
|
| }
|
| -
|
| +
|
| while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->isDescendantOf(highestRoot))
|
| p = isAtomicNode(p.deprecatedNode()) ? positionInParentBeforeNode(p.deprecatedNode()) : previousVisuallyDistinctCandidate(p);
|
| -
|
| +
|
| if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecatedNode()->isDescendantOf(highestRoot))
|
| return VisiblePosition();
|
| -
|
| +
|
| return VisiblePosition(p);
|
| }
|
|
|
| @@ -313,8 +313,8 @@ bool isInline(const Node* node)
|
| }
|
|
|
| // FIXME: Deploy this in all of the places where enclosingBlockFlow/enclosingBlockFlowOrTableElement are used.
|
| -// FIXME: Pass a position to this function. The enclosing block of [table, x] for example, should be the
|
| -// block that contains the table and not the table, and this function should be the only one responsible for
|
| +// FIXME: Pass a position to this function. The enclosing block of [table, x] for example, should be the
|
| +// block that contains the table and not the table, and this function should be the only one responsible for
|
| // knowing about these kinds of special cases.
|
| Element* enclosingBlock(Node* node, EditingBoundaryCrossingRule rule)
|
| {
|
| @@ -372,7 +372,7 @@ String stringWithRebalancedWhitespace(const String& string, bool startIsStartOfP
|
| rebalancedString[i] = ' ';
|
| previousCharacterWasSpace = true;
|
| }
|
| -
|
| +
|
| }
|
|
|
| return String::adopt(rebalancedString);
|
| @@ -395,7 +395,7 @@ bool isSpecialElement(const Node *n)
|
| {
|
| if (!n)
|
| return false;
|
| -
|
| +
|
| if (!n->isHTMLElement())
|
| return false;
|
|
|
| @@ -405,7 +405,7 @@ bool isSpecialElement(const Node *n)
|
| RenderObject* renderer = n->renderer();
|
| if (!renderer)
|
| return false;
|
| -
|
| +
|
| if (renderer->style()->display() == TABLE || renderer->style()->display() == INLINE_TABLE)
|
| return true;
|
|
|
| @@ -414,7 +414,7 @@ bool isSpecialElement(const Node *n)
|
|
|
| if (renderer->style()->position() != StaticPosition)
|
| return true;
|
| -
|
| +
|
| return false;
|
| }
|
|
|
| @@ -479,7 +479,7 @@ Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition)
|
| Position upstream(visiblePosition.deepEquivalent().upstream());
|
| if (upstream.deprecatedNode() && upstream.deprecatedNode()->renderer() && upstream.deprecatedNode()->renderer()->isTable() && upstream.atLastEditingPositionForNode())
|
| return upstream.deprecatedNode();
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -488,7 +488,7 @@ Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition)
|
| Position downstream(visiblePosition.deepEquivalent().downstream());
|
| if (downstream.deprecatedNode() && downstream.deprecatedNode()->renderer() && downstream.deprecatedNode()->renderer()->isTable() && downstream.atFirstEditingPositionForNode())
|
| return downstream.deprecatedNode();
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -541,7 +541,7 @@ Node* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName)
|
| {
|
| if (p.isNull())
|
| return 0;
|
| -
|
| +
|
| Node* root = highestEditableRoot(p);
|
| for (Node* n = p.deprecatedNode(); n; n = n->parentNode()) {
|
| if (root && !n->rendererIsEditable())
|
| @@ -551,7 +551,7 @@ Node* enclosingNodeWithTag(const Position& p, const QualifiedName& tagName)
|
| if (n == root)
|
| return 0;
|
| }
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -561,7 +561,7 @@ Node* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*),
|
| ASSERT(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary);
|
| if (p.isNull())
|
| return 0;
|
| -
|
| +
|
| Node* root = rule == CannotCrossEditingBoundary ? highestEditableRoot(p) : 0;
|
| for (Node* n = p.deprecatedNode(); n; n = n->parentNode()) {
|
| // Don't return a non-editable node if the input position was editable, since
|
| @@ -573,7 +573,7 @@ Node* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*),
|
| if (n == root)
|
| return 0;
|
| }
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -589,7 +589,7 @@ Node* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const N
|
| if (n == root)
|
| break;
|
| }
|
| -
|
| +
|
| return highest;
|
| }
|
|
|
| @@ -630,7 +630,7 @@ Element* enclosingAnchorElement(const Position& p)
|
| {
|
| if (p.isNull())
|
| return 0;
|
| -
|
| +
|
| Node* node = p.deprecatedNode();
|
| while (node && !(node->isElementNode() && node->isLink()))
|
| node = node->parentNode();
|
| @@ -641,16 +641,16 @@ HTMLElement* enclosingList(Node* node)
|
| {
|
| if (!node)
|
| return 0;
|
| -
|
| +
|
| Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
|
| -
|
| +
|
| for (ContainerNode* n = node->parentNode(); n; n = n->parentNode()) {
|
| if (n->hasTagName(ulTag) || n->hasTagName(olTag))
|
| return toHTMLElement(n);
|
| if (n == root)
|
| return 0;
|
| }
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -661,7 +661,7 @@ Node* enclosingListChild(Node *node)
|
| // Check for a list item element, or for a node whose parent is a list element. Such a node
|
| // will appear visually as a list item (but without a list marker)
|
| Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
|
| -
|
| +
|
| // FIXME: This function is inappropriately named if it starts with node instead of node->parentNode()
|
| for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
|
| if (n->hasTagName(liTag) || (isListElement(n->parentNode()) && n != root))
|
| @@ -669,7 +669,7 @@ Node* enclosingListChild(Node *node)
|
| if (n == root || isTableCell(n))
|
| return 0;
|
| }
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -680,7 +680,7 @@ static HTMLElement* embeddedSublist(Node* listItem)
|
| if (isListElement(n))
|
| return toHTMLElement(n);
|
| }
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -693,7 +693,7 @@ static Node* appendedSublist(Node* listItem)
|
| if (isListItem(listItem))
|
| return 0;
|
| }
|
| -
|
| +
|
| return 0;
|
| }
|
|
|
| @@ -710,10 +710,10 @@ Node* enclosingEmptyListItem(const VisiblePosition& visiblePos)
|
|
|
| if (firstInListChild != visiblePos || lastInListChild != visiblePos)
|
| return 0;
|
| -
|
| +
|
| if (embeddedSublist(listChildNode) || appendedSublist(listChildNode))
|
| return 0;
|
| -
|
| +
|
| return listChildNode;
|
| }
|
|
|
| @@ -768,7 +768,7 @@ bool isTableCell(const Node* node)
|
| RenderObject* r = node->renderer();
|
| if (!r)
|
| return node->hasTagName(tdTag) || node->hasTagName(thTag);
|
| -
|
| +
|
| return r->isTableCell();
|
| }
|
|
|
| @@ -862,7 +862,7 @@ Node* tabSpanNode(const Node *node)
|
| {
|
| return isTabSpanTextNode(node) ? node->parentNode() : 0;
|
| }
|
| -
|
| +
|
| Position positionOutsideTabSpan(const Position& pos)
|
| {
|
| Node* node = pos.containerNode();
|
| @@ -923,7 +923,7 @@ unsigned numEnclosingMailBlockquotes(const Position& p)
|
| for (Node* n = p.deprecatedNode(); n; n = n->parentNode())
|
| if (isMailBlockquote(n))
|
| num++;
|
| -
|
| +
|
| return num;
|
| }
|
|
|
| @@ -961,7 +961,7 @@ bool isMailBlockquote(const Node *node)
|
| {
|
| if (!node || !node->hasTagName(blockquoteTag))
|
| return false;
|
| -
|
| +
|
| return toElement(node)->getAttribute("type") == "cite";
|
| }
|
|
|
| @@ -972,7 +972,7 @@ int caretMinOffset(const Node* n)
|
| return r ? r->caretMinOffset() : 0;
|
| }
|
|
|
| -// If a node can contain candidates for VisiblePositions, return the offset of the last candidate, otherwise
|
| +// If a node can contain candidates for VisiblePositions, return the offset of the last candidate, otherwise
|
| // return the number of children for container nodes and the length for unrendered text nodes.
|
| int caretMaxOffset(const Node* n)
|
| {
|
| @@ -992,16 +992,16 @@ bool lineBreakExistsAtPosition(const Position& position)
|
| {
|
| if (position.isNull())
|
| return false;
|
| -
|
| +
|
| if (position.anchorNode()->hasTagName(brTag) && position.atFirstEditingPositionForNode())
|
| return true;
|
| -
|
| +
|
| if (!position.anchorNode()->renderer())
|
| return false;
|
| -
|
| +
|
| if (!position.anchorNode()->isTextNode() || !position.anchorNode()->renderer()->style()->preserveNewline())
|
| return false;
|
| -
|
| +
|
| Text* textNode = toText(position.anchorNode());
|
| unsigned offset = position.offsetInContainerNode();
|
| return offset < textNode->length() && textNode->data()[offset] == '\n';
|
| @@ -1015,7 +1015,7 @@ VisibleSelection selectionForParagraphIteration(const VisibleSelection& original
|
| VisibleSelection newSelection(original);
|
| VisiblePosition startOfSelection(newSelection.visibleStart());
|
| VisiblePosition endOfSelection(newSelection.visibleEnd());
|
| -
|
| +
|
| // If the end of the selection to modify is just after a table, and
|
| // if the start of the selection is inside that table, then the last paragraph
|
| // that we'll want modify is the last one inside the table, not the table itself
|
| @@ -1023,7 +1023,7 @@ VisibleSelection selectionForParagraphIteration(const VisibleSelection& original
|
| if (Node* table = isFirstPositionAfterTable(endOfSelection))
|
| if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(table))
|
| newSelection = VisibleSelection(startOfSelection, endOfSelection.previous(CannotCrossEditingBoundary));
|
| -
|
| +
|
| // If the start of the selection to modify is just before a table,
|
| // and if the end of the selection is inside that table, then the first paragraph
|
| // we'll want to modify is the first one inside the table, not the paragraph
|
| @@ -1031,14 +1031,14 @@ VisibleSelection selectionForParagraphIteration(const VisibleSelection& original
|
| if (Node* table = isLastPositionBeforeTable(startOfSelection))
|
| if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(table))
|
| newSelection = VisibleSelection(startOfSelection.next(CannotCrossEditingBoundary), endOfSelection);
|
| -
|
| +
|
| return newSelection;
|
| }
|
|
|
| -// FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators to convert between
|
| -// VisiblePositions and indices. But TextIterator iteration using TextIteratorEmitsCharactersBetweenAllVisiblePositions
|
| -// does not exactly match VisiblePosition iteration, so using them to preserve a selection during an editing
|
| -// opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllVisiblePositions mode needs to be fixed,
|
| +// FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators to convert between
|
| +// VisiblePositions and indices. But TextIterator iteration using TextIteratorEmitsCharactersBetweenAllVisiblePositions
|
| +// does not exactly match VisiblePosition iteration, so using them to preserve a selection during an editing
|
| +// opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllVisiblePositions mode needs to be fixed,
|
| // or these functions need to be changed to iterate using actual VisiblePositions.
|
| // FIXME: Deploy these functions everywhere that TextIterators are used to convert between VisiblePositions and indices.
|
| int indexForVisiblePosition(const VisiblePosition& visiblePosition, RefPtr<ContainerNode>& scope)
|
| @@ -1063,7 +1063,7 @@ int indexForVisiblePosition(const VisiblePosition& visiblePosition, RefPtr<Conta
|
| VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope)
|
| {
|
| RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(scope, index, 0, true);
|
| - // Check for an invalid index. Certain editing operations invalidate indices because
|
| + // Check for an invalid index. Certain editing operations invalidate indices because
|
| // of problems with TextIteratorEmitsCharactersBetweenAllVisiblePositions.
|
| if (!range)
|
| return VisiblePosition();
|
| @@ -1133,12 +1133,12 @@ bool isNonTableCellHTMLBlockElement(const Node* node)
|
| || node->hasTagName(h4Tag)
|
| || node->hasTagName(h5Tag);
|
| }
|
| -
|
| +
|
| Position adjustedSelectionStartForStyleComputation(const VisibleSelection& selection)
|
| {
|
| // This function is used by range style computations to avoid bugs like:
|
| // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once
|
| - // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up
|
| + // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up
|
| // with a spurious "mixed" style.
|
|
|
| VisiblePosition visiblePosition = selection.start();
|
|
|