Roll out r165076.
[WebKit-https.git] / Source / WebCore / editing / htmlediting.cpp
1 /*
2  * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "config.h"
27 #include "htmlediting.h"
28
29 #include "AXObjectCache.h"
30 #include "Document.h"
31 #include "Editor.h"
32 #include "ExceptionCodePlaceholder.h"
33 #include "Frame.h"
34 #include "HTMLBRElement.h"
35 #include "HTMLDivElement.h"
36 #include "HTMLElementFactory.h"
37 #include "HTMLInterchange.h"
38 #include "HTMLLIElement.h"
39 #include "HTMLNames.h"
40 #include "HTMLOListElement.h"
41 #include "HTMLObjectElement.h"
42 #include "HTMLParagraphElement.h"
43 #include "HTMLTableElement.h"
44 #include "HTMLTextFormControlElement.h"
45 #include "HTMLUListElement.h"
46 #include "NodeTraversal.h"
47 #include "PositionIterator.h"
48 #include "RenderBlock.h"
49 #include "RenderElement.h"
50 #include "RenderTableCell.h"
51 #include "ShadowRoot.h"
52 #include "Text.h"
53 #include "TextIterator.h"
54 #include "VisibleUnits.h"
55 #include <wtf/Assertions.h>
56 #include <wtf/StdLibExtras.h>
57 #include <wtf/unicode/CharacterNames.h>
58
59 namespace WebCore {
60
61 using namespace HTMLNames;
62
63 // Atomic means that the node has no children, or has children which are ignored for the
64 // purposes of editing.
65 bool isAtomicNode(const Node *node)
66 {
67     return node && (!node->hasChildNodes() || editingIgnoresContent(node));
68 }
69
70 // Compare two positions, taking into account the possibility that one or both
71 // could be inside a shadow tree. Only works for non-null values.
72 int comparePositions(const Position& a, const Position& b)
73 {
74     TreeScope* commonScope = commonTreeScope(a.containerNode(), b.containerNode());
75
76     if (!commonScope)
77         return 0;
78
79     Node* nodeA = commonScope->ancestorInThisScope(a.containerNode());
80     ASSERT(nodeA);
81     bool hasDescendentA = nodeA != a.containerNode();
82     int offsetA = hasDescendentA ? 0 : a.computeOffsetInContainerNode();
83
84     Node* nodeB = commonScope->ancestorInThisScope(b.containerNode());
85     ASSERT(nodeB);
86     bool hasDescendentB = nodeB != b.containerNode();
87     int offsetB = hasDescendentB ? 0 : b.computeOffsetInContainerNode();
88
89     int bias = 0;
90     if (nodeA == nodeB) {
91         if (hasDescendentA)
92             bias = -1;
93         else if (hasDescendentB)
94             bias = 1;
95     }
96
97     int result = Range::compareBoundaryPoints(nodeA, offsetA, nodeB, offsetB, IGNORE_EXCEPTION);
98     return result ? result : bias;
99 }
100
101 int comparePositions(const VisiblePosition& a, const VisiblePosition& b)
102 {
103     return comparePositions(a.deepEquivalent(), b.deepEquivalent());
104 }
105
106 Node* highestEditableRoot(const Position& position, EditableType editableType)
107 {
108     Node* node = position.deprecatedNode();
109     if (!node)
110         return 0;
111
112     Node* highestEditableRoot = editableRootForPosition(position, editableType);
113     if (!highestEditableRoot)
114         return 0;
115
116     node = highestEditableRoot;
117     while (!node->hasTagName(bodyTag)) {
118         node = node->parentNode();
119         if (!node)
120             break;
121         if (node->hasEditableStyle(editableType))
122             highestEditableRoot = node;
123     }
124
125     return highestEditableRoot;
126 }
127
128 Node* lowestEditableAncestor(Node* node)
129 {
130     if (!node)
131         return 0;
132     
133     while (node) {
134         if (node->hasEditableStyle())
135             return node->rootEditableElement();
136         if (node->hasTagName(bodyTag))
137             break;
138         node = node->parentNode();
139     }
140     
141     return 0;
142 }
143
144 bool isEditablePosition(const Position& p, EditableType editableType, EUpdateStyle updateStyle)
145 {
146     Node* node = p.deprecatedNode();
147     if (!node)
148         return false;
149     if (updateStyle == UpdateStyle)
150         node->document().updateStyleIfNeeded();
151     else
152         ASSERT(updateStyle == DoNotUpdateStyle);
153
154     if (node->renderer() && node->renderer()->isTable())
155         node = node->parentNode();
156
157     return node->hasEditableStyle(editableType);
158 }
159
160 bool isAtUnsplittableElement(const Position& pos)
161 {
162     Node* node = pos.deprecatedNode();
163     return (node == editableRootForPosition(pos) || node == enclosingNodeOfType(pos, &isTableCell));
164 }
165     
166     
167 bool isRichlyEditablePosition(const Position& p, EditableType editableType)
168 {
169     Node* node = p.deprecatedNode();
170     if (!node)
171         return false;
172         
173     if (node->renderer() && node->renderer()->isTable())
174         node = node->parentNode();
175     
176     return node->hasRichlyEditableStyle(editableType);
177 }
178
179 Element* editableRootForPosition(const Position& p, EditableType editableType)
180 {
181     Node* node = p.containerNode();
182     if (!node)
183         return 0;
184         
185     if (node->renderer() && node->renderer()->isTable())
186         node = node->parentNode();
187     
188     return node->rootEditableElement(editableType);
189 }
190
191 // Finds the enclosing element until which the tree can be split.
192 // When a user hits ENTER, he/she won't expect this element to be split into two.
193 // You may pass it as the second argument of splitTreeToNode.
194 Element* unsplittableElementForPosition(const Position& p)
195 {
196     // Since enclosingNodeOfType won't search beyond the highest root editable node,
197     // this code works even if the closest table cell was outside of the root editable node.
198     Element* enclosingCell = downcast<Element>(enclosingNodeOfType(p, &isTableCell));
199     if (enclosingCell)
200         return enclosingCell;
201
202     return editableRootForPosition(p);
203 }
204
205 Position nextCandidate(const Position& position)
206 {
207     PositionIterator p = position;
208     while (!p.atEnd()) {
209         p.increment();
210         if (p.isCandidate())
211             return p;
212     }
213     return Position();
214 }
215
216 Position nextVisuallyDistinctCandidate(const Position& position)
217 {
218     Position p = position;
219     Position downstreamStart = p.downstream();
220     while (!p.atEndOfTree()) {
221         p = p.next(Character);
222         if (p.isCandidate() && p.downstream() != downstreamStart)
223             return p;
224     }
225     return Position();
226 }
227
228 Position previousCandidate(const Position& position)
229 {
230     PositionIterator p = position;
231     while (!p.atStart()) {
232         p.decrement();
233         if (p.isCandidate())
234             return p;
235     }
236     return Position();
237 }
238
239 Position previousVisuallyDistinctCandidate(const Position& position)
240 {
241     Position p = position;
242     Position downstreamStart = p.downstream();
243     while (!p.atStartOfTree()) {
244         p = p.previous(Character);
245         if (p.isCandidate() && p.downstream() != downstreamStart)
246             return p;
247     }
248     return Position();
249 }
250
251 VisiblePosition firstEditablePositionAfterPositionInRoot(const Position& position, Node* highestRoot)
252 {
253     // position falls before highestRoot.
254     if (comparePositions(position, firstPositionInNode(highestRoot)) == -1 && highestRoot->hasEditableStyle())
255         return firstPositionInNode(highestRoot);
256
257     Position p = position;
258
259     if (&position.deprecatedNode()->treeScope() != &highestRoot->treeScope()) {
260         Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(p.deprecatedNode());
261         if (!shadowAncestor)
262             return VisiblePosition();
263
264         p = positionAfterNode(shadowAncestor);
265     }
266
267     while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->isDescendantOf(highestRoot))
268         p = isAtomicNode(p.deprecatedNode()) ? positionInParentAfterNode(p.deprecatedNode()) : nextVisuallyDistinctCandidate(p);
269     
270     if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecatedNode()->isDescendantOf(highestRoot))
271         return VisiblePosition();
272     
273     return VisiblePosition(p);
274 }
275
276 VisiblePosition lastEditablePositionBeforePositionInRoot(const Position& position, Node* highestRoot)
277 {
278     // When position falls after highestRoot, the result is easy to compute.
279     if (comparePositions(position, lastPositionInNode(highestRoot)) == 1)
280         return lastPositionInNode(highestRoot);
281
282     Position p = position;
283
284     if (&position.deprecatedNode()->treeScope() != &highestRoot->treeScope()) {
285         Node* shadowAncestor = highestRoot->treeScope().ancestorInThisScope(p.deprecatedNode());
286         if (!shadowAncestor)
287             return VisiblePosition();
288
289         p = firstPositionInOrBeforeNode(shadowAncestor);
290     }
291     
292     while (p.deprecatedNode() && !isEditablePosition(p) && p.deprecatedNode()->isDescendantOf(highestRoot))
293         p = isAtomicNode(p.deprecatedNode()) ? positionInParentBeforeNode(p.deprecatedNode()) : previousVisuallyDistinctCandidate(p);
294     
295     if (p.deprecatedNode() && p.deprecatedNode() != highestRoot && !p.deprecatedNode()->isDescendantOf(highestRoot))
296         return VisiblePosition();
297     
298     return VisiblePosition(p);
299 }
300
301 // FIXME: The method name, comment, and code say three different things here!
302 // Whether or not content before and after this node will collapse onto the same line as it.
303 bool isBlock(const Node* node)
304 {
305     return node && node->renderer() && !node->renderer()->isInline() && !node->renderer()->isRubyText();
306 }
307
308 bool isInline(const Node* node)
309 {
310     return node && node->renderer() && node->renderer()->isInline();
311 }
312
313 // FIXME: Deploy this in all of the places where enclosingBlockFlow/enclosingBlockFlowOrTableElement are used.
314 // FIXME: Pass a position to this function. The enclosing block of [table, x] for example, should be the 
315 // block that contains the table and not the table, and this function should be the only one responsible for 
316 // knowing about these kinds of special cases.
317 Element* enclosingBlock(Node* node, EditingBoundaryCrossingRule rule)
318 {
319     Node* enclosingNode = enclosingNodeOfType(firstPositionInOrBeforeNode(node), isBlock, rule);
320     return is<Element>(enclosingNode) ? downcast<Element>(enclosingNode) : nullptr;
321 }
322
323 TextDirection directionOfEnclosingBlock(const Position& position)
324 {
325     auto block = enclosingBlock(position.containerNode());
326     if (!block)
327         return LTR;
328     auto renderer = block->renderer();
329     if (!renderer)
330         return LTR;
331     return renderer->style().direction();
332 }
333
334 // This method is used to create positions in the DOM. It returns the maximum valid offset
335 // in a node. It returns 1 for some elements even though they do not have children, which
336 // creates technically invalid DOM Positions. Be sure to call parentAnchoredEquivalent
337 // on a Position before using it to create a DOM Range, or an exception will be thrown.
338 int lastOffsetForEditing(const Node* node)
339 {
340     ASSERT(node);
341     if (!node)
342         return 0;
343     if (node->offsetInCharacters())
344         return node->maxCharacterOffset();
345
346     if (node->hasChildNodes())
347         return node->countChildNodes();
348
349     // NOTE: This should preempt the countChildNodes() for, e.g., select nodes (what does this mean)?
350     if (editingIgnoresContent(node))
351         return 1;
352
353     return 0;
354 }
355
356 String stringWithRebalancedWhitespace(const String& string, bool startIsStartOfParagraph, bool endIsEndOfParagraph)
357 {
358     Vector<UChar> rebalancedString(string.length());
359     StringView(string).getCharactersWithUpconvert(rebalancedString.data());
360
361     bool previousCharacterWasSpace = false;
362     for (size_t i = 0; i < rebalancedString.size(); i++) {
363         if (!isWhitespace(rebalancedString[i])) {
364             previousCharacterWasSpace = false;
365             continue;
366         }
367
368         if (previousCharacterWasSpace || (!i && startIsStartOfParagraph) || (i + 1 == rebalancedString.size() && endIsEndOfParagraph)) {
369             rebalancedString[i] = noBreakSpace;
370             previousCharacterWasSpace = false;
371         } else {
372             rebalancedString[i] = ' ';
373             previousCharacterWasSpace = true;
374         }
375     }
376
377     return String::adopt(rebalancedString);
378 }
379
380 bool isTableStructureNode(const Node *node)
381 {
382     RenderObject* renderer = node->renderer();
383     return (renderer && (renderer->isTableCell() || renderer->isTableRow() || renderer->isTableSection() || renderer->isRenderTableCol()));
384 }
385
386 const String& nonBreakingSpaceString()
387 {
388     DEPRECATED_DEFINE_STATIC_LOCAL(String, nonBreakingSpaceString, (&noBreakSpace, 1));
389     return nonBreakingSpaceString;
390 }
391
392 // FIXME: need to dump this
393 bool isSpecialElement(const Node *n)
394 {
395     if (!n)
396         return false;
397         
398     if (!n->isHTMLElement())
399         return false;
400
401     if (n->isLink())
402         return true;
403
404     RenderObject* renderer = n->renderer();
405     if (!renderer)
406         return false;
407         
408     if (renderer->style().display() == TABLE || renderer->style().display() == INLINE_TABLE)
409         return true;
410
411     if (renderer->style().isFloating())
412         return true;
413
414     if (renderer->style().position() != StaticPosition)
415         return true;
416         
417     return false;
418 }
419
420 static Node* firstInSpecialElement(const Position& pos)
421 {
422     Node* rootEditableElement = pos.containerNode()->rootEditableElement();
423     for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
424         if (isSpecialElement(n)) {
425             VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
426             VisiblePosition firstInElement = VisiblePosition(firstPositionInOrBeforeNode(n), DOWNSTREAM);
427             if (isRenderedTable(n) && vPos == firstInElement.next())
428                 return n;
429             if (vPos == firstInElement)
430                 return n;
431         }
432     return 0;
433 }
434
435 static Node* lastInSpecialElement(const Position& pos)
436 {
437     Node* rootEditableElement = pos.containerNode()->rootEditableElement();
438     for (Node* n = pos.deprecatedNode(); n && n->rootEditableElement() == rootEditableElement; n = n->parentNode())
439         if (isSpecialElement(n)) {
440             VisiblePosition vPos = VisiblePosition(pos, DOWNSTREAM);
441             VisiblePosition lastInElement = VisiblePosition(lastPositionInOrAfterNode(n), DOWNSTREAM);
442             if (isRenderedTable(n) && vPos == lastInElement.previous())
443                 return n;
444             if (vPos == lastInElement)
445                 return n;
446         }
447     return 0;
448 }
449
450 bool isFirstVisiblePositionInSpecialElement(const Position& pos)
451 {
452     return firstInSpecialElement(pos);
453 }
454
455 Position positionBeforeContainingSpecialElement(const Position& pos, Node** containingSpecialElement)
456 {
457     Node* n = firstInSpecialElement(pos);
458     if (!n)
459         return pos;
460     Position result = positionInParentBeforeNode(n);
461     if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos.deprecatedNode()->rootEditableElement())
462         return pos;
463     if (containingSpecialElement)
464         *containingSpecialElement = n;
465     return result;
466 }
467
468 bool isLastVisiblePositionInSpecialElement(const Position& pos)
469 {
470     return lastInSpecialElement(pos);
471 }
472
473 Position positionAfterContainingSpecialElement(const Position& pos, Node **containingSpecialElement)
474 {
475     Node* n = lastInSpecialElement(pos);
476     if (!n)
477         return pos;
478     Position result = positionInParentAfterNode(n);
479     if (result.isNull() || result.deprecatedNode()->rootEditableElement() != pos.deprecatedNode()->rootEditableElement())
480         return pos;
481     if (containingSpecialElement)
482         *containingSpecialElement = n;
483     return result;
484 }
485
486 Position positionOutsideContainingSpecialElement(const Position &pos, Node **containingSpecialElement)
487 {
488     if (isFirstVisiblePositionInSpecialElement(pos))
489         return positionBeforeContainingSpecialElement(pos, containingSpecialElement);
490     if (isLastVisiblePositionInSpecialElement(pos))
491         return positionAfterContainingSpecialElement(pos, containingSpecialElement);
492     return pos;
493 }
494
495 Node* isFirstPositionAfterTable(const VisiblePosition& visiblePosition)
496 {
497     Position upstream(visiblePosition.deepEquivalent().upstream());
498     if (upstream.deprecatedNode() && upstream.deprecatedNode()->renderer() && upstream.deprecatedNode()->renderer()->isTable() && upstream.atLastEditingPositionForNode())
499         return upstream.deprecatedNode();
500     
501     return 0;
502 }
503
504 Node* isLastPositionBeforeTable(const VisiblePosition& visiblePosition)
505 {
506     Position downstream(visiblePosition.deepEquivalent().downstream());
507     if (downstream.deprecatedNode() && downstream.deprecatedNode()->renderer() && downstream.deprecatedNode()->renderer()->isTable() && downstream.atFirstEditingPositionForNode())
508         return downstream.deprecatedNode();
509     
510     return 0;
511 }
512
513 // Returns the visible position at the beginning of a node
514 VisiblePosition visiblePositionBeforeNode(Node* node)
515 {
516     ASSERT(node);
517     if (node->hasChildNodes())
518         return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
519     ASSERT(node->parentNode());
520     ASSERT(!node->parentNode()->isShadowRoot());
521     return positionInParentBeforeNode(node);
522 }
523
524 // Returns the visible position at the ending of a node
525 VisiblePosition visiblePositionAfterNode(Node* node)
526 {
527     ASSERT(node);
528     if (node->hasChildNodes())
529         return VisiblePosition(lastPositionInOrAfterNode(node), DOWNSTREAM);
530     ASSERT(node->parentNode());
531     ASSERT(!node->parentNode()->isShadowRoot());
532     return positionInParentAfterNode(node);
533 }
534
535 bool isListElement(Node *n)
536 {
537     return (n && (n->hasTagName(ulTag) || n->hasTagName(olTag) || n->hasTagName(dlTag)));
538 }
539
540 bool isListItem(const Node *n)
541 {
542     return n && (isListElement(n->parentNode()) || (n->renderer() && n->renderer()->isListItem()));
543 }
544
545 Element* enclosingElementWithTag(const Position& position, const QualifiedName& tagName)
546 {
547     if (position.isNull())
548         return nullptr;
549
550     Node* root = highestEditableRoot(position);
551     for (Node* node = position.deprecatedNode(); node; node = node->parentNode()) {
552         if (root && !node->hasEditableStyle())
553             continue;
554         if (!is<Element>(*node))
555             continue;
556         if (downcast<Element>(*node).hasTagName(tagName))
557             return downcast<Element>(node);
558         if (node == root)
559             return nullptr;
560     }
561
562     return nullptr;
563 }
564
565 Node* enclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule)
566 {
567     // FIXME: support CanSkipCrossEditingBoundary
568     ASSERT(rule == CanCrossEditingBoundary || rule == CannotCrossEditingBoundary);
569     if (p.isNull())
570         return 0;
571         
572     Node* root = rule == CannotCrossEditingBoundary ? highestEditableRoot(p) : 0;
573     for (Node* n = p.deprecatedNode(); n; n = n->parentNode()) {
574         // Don't return a non-editable node if the input position was editable, since
575         // the callers from editing will no doubt want to perform editing inside the returned node.
576         if (root && !n->hasEditableStyle())
577             continue;
578         if (nodeIsOfType(n))
579             return n;
580         if (n == root)
581             return 0;
582     }
583     
584     return 0;
585 }
586
587 Node* highestEnclosingNodeOfType(const Position& p, bool (*nodeIsOfType)(const Node*), EditingBoundaryCrossingRule rule, Node* stayWithin)
588 {
589     Node* highest = 0;
590     Node* root = rule == CannotCrossEditingBoundary ? highestEditableRoot(p) : 0;
591     for (Node* n = p.containerNode(); n && n != stayWithin; n = n->parentNode()) {
592         if (root && !n->hasEditableStyle())
593             continue;
594         if (nodeIsOfType(n))
595             highest = n;
596         if (n == root)
597             break;
598     }
599     
600     return highest;
601 }
602
603 static bool hasARenderedDescendant(Node* node, Node* excludedNode)
604 {
605     for (Node* n = node->firstChild(); n;) {
606         if (n == excludedNode) {
607             n = NodeTraversal::nextSkippingChildren(n, node);
608             continue;
609         }
610         if (n->renderer())
611             return true;
612         n = NodeTraversal::next(n, node);
613     }
614     return false;
615 }
616
617 Node* highestNodeToRemoveInPruning(Node* node)
618 {
619     Node* previousNode = 0;
620     Node* rootEditableElement = node ? node->rootEditableElement() : 0;
621     for (; node; node = node->parentNode()) {
622         if (RenderObject* renderer = node->renderer()) {
623             if (!renderer->canHaveChildren() || hasARenderedDescendant(node, previousNode) || rootEditableElement == node)
624                 return previousNode;
625         }
626         previousNode = node;
627     }
628     return 0;
629 }
630
631 Node* enclosingTableCell(const Position& p)
632 {
633     return downcast<Element>(enclosingNodeOfType(p, isTableCell));
634 }
635
636 Element* enclosingAnchorElement(const Position& p)
637 {
638     if (p.isNull())
639         return nullptr;
640
641     for (Node* node = p.deprecatedNode(); node; node = node->parentNode()) {
642         if (is<Element>(*node) && node->isLink())
643             return downcast<Element>(node);
644     }
645     return nullptr;
646 }
647
648 HTMLElement* enclosingList(Node* node)
649 {
650     if (!node)
651         return nullptr;
652         
653     Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
654     
655     for (ContainerNode* ancestor = node->parentNode(); ancestor; ancestor = ancestor->parentNode()) {
656         if (is<HTMLUListElement>(*ancestor) || is<HTMLOListElement>(*ancestor))
657             return downcast<HTMLElement>(ancestor);
658         if (ancestor == root)
659             return nullptr;
660     }
661     
662     return nullptr;
663 }
664
665 Node* enclosingListChild(Node *node)
666 {
667     if (!node)
668         return nullptr;
669     // Check for a list item element, or for a node whose parent is a list element. Such a node
670     // will appear visually as a list item (but without a list marker)
671     Node* root = highestEditableRoot(firstPositionInOrBeforeNode(node));
672     
673     // FIXME: This function is inappropriately named if it starts with node instead of node->parentNode()
674     for (Node* n = node; n && n->parentNode(); n = n->parentNode()) {
675         if (n->hasTagName(liTag) || (isListElement(n->parentNode()) && n != root))
676             return n;
677         if (n == root || isTableCell(n))
678             return nullptr;
679     }
680     
681     return nullptr;
682 }
683
684 static HTMLElement* embeddedSublist(Node* listItem)
685 {
686     // Check the DOM so that we'll find collapsed sublists without renderers.
687     for (Node* n = listItem->firstChild(); n; n = n->nextSibling()) {
688         if (isListElement(n))
689             return downcast<HTMLElement>(n);
690     }
691     
692     return nullptr;
693 }
694
695 static Node* appendedSublist(Node* listItem)
696 {
697     // Check the DOM so that we'll find collapsed sublists without renderers.
698     for (Node* n = listItem->nextSibling(); n; n = n->nextSibling()) {
699         if (isListElement(n))
700             return downcast<HTMLElement>(n);
701         if (isListItem(listItem))
702             return nullptr;
703     }
704     
705     return nullptr;
706 }
707
708 // FIXME: This method should not need to call isStartOfParagraph/isEndOfParagraph
709 Node* enclosingEmptyListItem(const VisiblePosition& visiblePos)
710 {
711     // Check that position is on a line by itself inside a list item
712     Node* listChildNode = enclosingListChild(visiblePos.deepEquivalent().deprecatedNode());
713     if (!listChildNode || !isStartOfParagraph(visiblePos) || !isEndOfParagraph(visiblePos))
714         return 0;
715
716     VisiblePosition firstInListChild(firstPositionInOrBeforeNode(listChildNode));
717     VisiblePosition lastInListChild(lastPositionInOrAfterNode(listChildNode));
718
719     if (firstInListChild != visiblePos || lastInListChild != visiblePos)
720         return 0;
721     
722     if (embeddedSublist(listChildNode) || appendedSublist(listChildNode))
723         return 0;
724         
725     return listChildNode;
726 }
727
728 HTMLElement* outermostEnclosingList(Node* node, Node* rootList)
729 {
730     HTMLElement* list = enclosingList(node);
731     if (!list)
732         return 0;
733
734     while (HTMLElement* nextList = enclosingList(list)) {
735         if (nextList == rootList)
736             break;
737         list = nextList;
738     }
739
740     return list;
741 }
742
743 bool canMergeLists(Element* firstList, Element* secondList)
744 {
745     if (!firstList || !secondList || !firstList->isHTMLElement() || !secondList->isHTMLElement())
746         return false;
747
748     return firstList->hasTagName(secondList->tagQName()) // make sure the list types match (ol vs. ul)
749     && firstList->hasEditableStyle() && secondList->hasEditableStyle() // both lists are editable
750     && firstList->rootEditableElement() == secondList->rootEditableElement() // don't cross editing boundaries
751     && isVisiblyAdjacent(positionInParentAfterNode(firstList), positionInParentBeforeNode(secondList));
752     // Make sure there is no visible content between this li and the previous list
753 }
754
755 Node* highestAncestor(Node* node)
756 {
757     ASSERT(node);
758     Node* parent = node;
759     while ((node = node->parentNode()))
760         parent = node;
761     return parent;
762 }
763
764 static Node* previousNodeConsideringAtomicNodes(const Node* node)
765 {
766     if (node->previousSibling()) {
767         Node* n = node->previousSibling();
768         while (!isAtomicNode(n) && n->lastChild())
769             n = n->lastChild();
770         return n;
771     }
772     if (node->parentNode())
773         return node->parentNode();
774     return 0;
775 }
776
777 static Node* nextNodeConsideringAtomicNodes(const Node* node)
778 {
779     if (!isAtomicNode(node) && node->firstChild())
780         return node->firstChild();
781     if (node->nextSibling())
782         return node->nextSibling();
783     const Node* n = node;
784     while (n && !n->nextSibling())
785         n = n->parentNode();
786     if (n)
787         return n->nextSibling();
788     return 0;
789 }
790
791 Node* previousLeafNode(const Node* node)
792 {
793     Node* n = previousNodeConsideringAtomicNodes(node);
794     while (n) {
795         if (isAtomicNode(n))
796             return n;
797         n = previousNodeConsideringAtomicNodes(n);
798     }
799     return 0;
800 }
801
802 Node* nextLeafNode(const Node* node)
803 {
804     Node* n = nextNodeConsideringAtomicNodes(node);
805     while (n) {
806         if (isAtomicNode(n))
807             return n;
808         n = nextNodeConsideringAtomicNodes(n);
809     }
810     return 0;
811 }
812
813 // FIXME: do not require renderer, so that this can be used within fragments
814 bool isRenderedTable(const Node* n)
815 {
816     if (!n || !n->isElementNode())
817         return false;
818
819     RenderObject* renderer = n->renderer();
820     return (renderer && renderer->isTable());
821 }
822
823 bool isTableCell(const Node* node)
824 {
825     RenderObject* r = node->renderer();
826     if (!r)
827         return node->hasTagName(tdTag) || node->hasTagName(thTag);
828     
829     return r->isTableCell();
830 }
831
832 bool isEmptyTableCell(const Node* node)
833 {
834     // Returns true IFF the passed in node is one of:
835     //   .) a table cell with no children,
836     //   .) a table cell with a single BR child, and which has no other child renderers, including :before and :after renderers
837     //   .) the BR child of such a table cell
838
839     // Find rendered node
840     while (node && !node->renderer())
841         node = node->parentNode();
842     if (!node)
843         return false;
844
845     // Make sure the rendered node is a table cell or <br>.
846     // If it's a <br>, then the parent node has to be a table cell.
847     RenderObject* renderer = node->renderer();
848     if (renderer->isBR()) {
849         renderer = renderer->parent();
850         if (!renderer)
851             return false;
852     }
853     if (!is<RenderTableCell>(*renderer))
854         return false;
855
856     // Check that the table cell contains no child renderers except for perhaps a single <br>.
857     RenderObject* childRenderer = downcast<RenderTableCell>(*renderer).firstChild();
858     if (!childRenderer)
859         return true;
860     if (!childRenderer->isBR())
861         return false;
862     return !childRenderer->nextSibling();
863 }
864
865 PassRefPtr<HTMLElement> createDefaultParagraphElement(Document& document)
866 {
867     switch (document.frame()->editor().defaultParagraphSeparator()) {
868     case EditorParagraphSeparatorIsDiv:
869         return HTMLDivElement::create(document);
870     case EditorParagraphSeparatorIsP:
871         return HTMLParagraphElement::create(document);
872     }
873
874     ASSERT_NOT_REACHED();
875     return 0;
876 }
877
878 PassRefPtr<HTMLElement> createBreakElement(Document& document)
879 {
880     return HTMLBRElement::create(document);
881 }
882
883 PassRefPtr<HTMLElement> createOrderedListElement(Document& document)
884 {
885     return HTMLOListElement::create(document);
886 }
887
888 PassRefPtr<HTMLElement> createUnorderedListElement(Document& document)
889 {
890     return HTMLUListElement::create(document);
891 }
892
893 PassRefPtr<HTMLElement> createListItemElement(Document& document)
894 {
895     return HTMLLIElement::create(document);
896 }
897
898 PassRefPtr<HTMLElement> createHTMLElement(Document& document, const QualifiedName& name)
899 {
900     return HTMLElementFactory::createElement(name, document);
901 }
902
903 PassRefPtr<HTMLElement> createHTMLElement(Document& document, const AtomicString& tagName)
904 {
905     return createHTMLElement(document, QualifiedName(nullAtom, tagName, xhtmlNamespaceURI));
906 }
907
908 bool isTabSpanNode(const Node *node)
909 {
910     return node && node->hasTagName(spanTag) && node->isElementNode() && static_cast<const Element *>(node)->getAttribute(classAttr) == AppleTabSpanClass;
911 }
912
913 bool isTabSpanTextNode(const Node *node)
914 {
915     return node && node->isTextNode() && node->parentNode() && isTabSpanNode(node->parentNode());
916 }
917
918 Node* tabSpanNode(const Node *node)
919 {
920     return isTabSpanTextNode(node) ? node->parentNode() : 0;
921 }
922     
923 Position positionOutsideTabSpan(const Position& pos)
924 {
925     Node* node = pos.containerNode();
926     if (isTabSpanTextNode(node))
927         node = tabSpanNode(node);
928     else if (!isTabSpanNode(node))
929         return pos;
930
931     if (node && VisiblePosition(pos) == lastPositionInNode(node))
932         return positionInParentAfterNode(node);
933
934     return positionInParentBeforeNode(node);
935 }
936
937 PassRefPtr<Element> createTabSpanElement(Document& document, PassRefPtr<Node> prpTabTextNode)
938 {
939     RefPtr<Node> tabTextNode = prpTabTextNode;
940
941     // Make the span to hold the tab.
942     RefPtr<Element> spanElement = document.createElement(spanTag, false);
943     spanElement->setAttribute(classAttr, AppleTabSpanClass);
944     spanElement->setAttribute(styleAttr, "white-space:pre");
945
946     // Add tab text to that span.
947     if (!tabTextNode)
948         tabTextNode = document.createEditingTextNode("\t");
949
950     spanElement->appendChild(tabTextNode.release(), ASSERT_NO_EXCEPTION);
951
952     return spanElement.release();
953 }
954
955 PassRefPtr<Element> createTabSpanElement(Document& document, const String& tabText)
956 {
957     return createTabSpanElement(document, document.createTextNode(tabText));
958 }
959
960 PassRefPtr<Element> createTabSpanElement(Document& document)
961 {
962     return createTabSpanElement(document, PassRefPtr<Node>());
963 }
964
965 bool isNodeRendered(const Node* node)
966 {
967     if (!node)
968         return false;
969
970     RenderObject* renderer = node->renderer();
971     if (!renderer)
972         return false;
973
974     return renderer->style().visibility() == VISIBLE;
975 }
976
977 unsigned numEnclosingMailBlockquotes(const Position& p)
978 {
979     unsigned num = 0;
980     for (Node* n = p.deprecatedNode(); n; n = n->parentNode())
981         if (isMailBlockquote(n))
982             num++;
983     
984     return num;
985 }
986
987 void updatePositionForNodeRemoval(Position& position, Node& node)
988 {
989     if (position.isNull())
990         return;
991     switch (position.anchorType()) {
992     case Position::PositionIsBeforeChildren:
993         if (node.containsIncludingShadowDOM(position.containerNode()))
994             position = positionInParentBeforeNode(&node);
995         break;
996     case Position::PositionIsAfterChildren:
997         if (node.containsIncludingShadowDOM(position.containerNode()))
998             position = positionInParentBeforeNode(&node);
999         break;
1000     case Position::PositionIsOffsetInAnchor:
1001         if (position.containerNode() == node.parentNode() && static_cast<unsigned>(position.offsetInContainerNode()) > node.computeNodeIndex())
1002             position.moveToOffset(position.offsetInContainerNode() - 1);
1003         else if (node.containsIncludingShadowDOM(position.containerNode()))
1004             position = positionInParentBeforeNode(&node);
1005         break;
1006     case Position::PositionIsAfterAnchor:
1007         if (node.containsIncludingShadowDOM(position.anchorNode()))
1008             position = positionInParentAfterNode(&node);
1009         break;
1010     case Position::PositionIsBeforeAnchor:
1011         if (node.containsIncludingShadowDOM(position.anchorNode()))
1012             position = positionInParentBeforeNode(&node);
1013         break;
1014     }
1015 }
1016
1017 bool isMailBlockquote(const Node *node)
1018 {
1019     if (!node || !node->hasTagName(blockquoteTag))
1020         return false;
1021         
1022     return static_cast<const Element *>(node)->getAttribute("type") == "cite";
1023 }
1024
1025 int caretMinOffset(const Node* n)
1026 {
1027     RenderObject* r = n->renderer();
1028     ASSERT(!n->isCharacterDataNode() || !r || r->isText()); // FIXME: This was a runtime check that seemingly couldn't fail; changed it to an assertion for now.
1029     return r ? r->caretMinOffset() : 0;
1030 }
1031
1032 // If a node can contain candidates for VisiblePositions, return the offset of the last candidate, otherwise 
1033 // return the number of children for container nodes and the length for unrendered text nodes.
1034 int caretMaxOffset(const Node* n)
1035 {
1036     // For rendered text nodes, return the last position that a caret could occupy.
1037     if (n->isTextNode() && n->renderer())
1038         return n->renderer()->caretMaxOffset();
1039     // For containers return the number of children. For others do the same as above.
1040     return lastOffsetForEditing(n);
1041 }
1042
1043 bool lineBreakExistsAtVisiblePosition(const VisiblePosition& visiblePosition)
1044 {
1045     return lineBreakExistsAtPosition(visiblePosition.deepEquivalent().downstream());
1046 }
1047
1048 bool lineBreakExistsAtPosition(const Position& position)
1049 {
1050     if (position.isNull())
1051         return false;
1052     
1053     if (position.anchorNode()->hasTagName(brTag) && position.atFirstEditingPositionForNode())
1054         return true;
1055     
1056     if (!position.anchorNode()->renderer())
1057         return false;
1058     
1059     if (!is<Text>(*position.anchorNode()) || !position.anchorNode()->renderer()->style().preserveNewline())
1060         return false;
1061     
1062     Text& textNode = downcast<Text>(*position.anchorNode());
1063     unsigned offset = position.offsetInContainerNode();
1064     return offset < textNode.length() && textNode.data()[offset] == '\n';
1065 }
1066
1067 // Modifies selections that have an end point at the edge of a table
1068 // that contains the other endpoint so that they don't confuse
1069 // code that iterates over selected paragraphs.
1070 VisibleSelection selectionForParagraphIteration(const VisibleSelection& original)
1071 {
1072     VisibleSelection newSelection(original);
1073     VisiblePosition startOfSelection(newSelection.visibleStart());
1074     VisiblePosition endOfSelection(newSelection.visibleEnd());
1075     
1076     // If the end of the selection to modify is just after a table, and
1077     // if the start of the selection is inside that table, then the last paragraph
1078     // that we'll want modify is the last one inside the table, not the table itself
1079     // (a table is itself a paragraph).
1080     if (Node* table = isFirstPositionAfterTable(endOfSelection))
1081         if (startOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(table))
1082             newSelection = VisibleSelection(startOfSelection, endOfSelection.previous(CannotCrossEditingBoundary));
1083     
1084     // If the start of the selection to modify is just before a table,
1085     // and if the end of the selection is inside that table, then the first paragraph
1086     // we'll want to modify is the first one inside the table, not the paragraph
1087     // containing the table itself.
1088     if (Node* table = isLastPositionBeforeTable(startOfSelection))
1089         if (endOfSelection.deepEquivalent().deprecatedNode()->isDescendantOf(table))
1090             newSelection = VisibleSelection(startOfSelection.next(CannotCrossEditingBoundary), endOfSelection);
1091     
1092     return newSelection;
1093 }
1094
1095 // FIXME: indexForVisiblePosition and visiblePositionForIndex use TextIterators to convert between 
1096 // VisiblePositions and indices. But TextIterator iteration using TextIteratorEmitsCharactersBetweenAllVisiblePositions 
1097 // does not exactly match VisiblePosition iteration, so using them to preserve a selection during an editing 
1098 // opertion is unreliable. TextIterator's TextIteratorEmitsCharactersBetweenAllVisiblePositions mode needs to be fixed, 
1099 // or these functions need to be changed to iterate using actual VisiblePositions.
1100 // FIXME: Deploy these functions everywhere that TextIterators are used to convert between VisiblePositions and indices.
1101 int indexForVisiblePosition(const VisiblePosition& visiblePosition, RefPtr<ContainerNode>& scope)
1102 {
1103     if (visiblePosition.isNull())
1104         return 0;
1105
1106     Position p(visiblePosition.deepEquivalent());
1107     Document& document = p.anchorNode()->document();
1108     ShadowRoot* shadowRoot = p.anchorNode()->containingShadowRoot();
1109
1110     if (shadowRoot)
1111         scope = shadowRoot;
1112     else
1113         scope = document.documentElement();
1114
1115     RefPtr<Range> range = Range::create(document, firstPositionInNode(scope.get()), p.parentAnchoredEquivalent());
1116     return TextIterator::rangeLength(range.get(), true);
1117 }
1118
1119 // FIXME: Merge these two functions.
1120 int indexForVisiblePosition(Node* node, const VisiblePosition& visiblePosition, bool forSelectionPreservation)
1121 {
1122     ASSERT(node);
1123     RefPtr<Range> range = Range::create(node->document(), firstPositionInNode(node), visiblePosition.deepEquivalent().parentAnchoredEquivalent());
1124     return TextIterator::rangeLength(range.get(), forSelectionPreservation);
1125 }
1126
1127 VisiblePosition visiblePositionForIndex(int index, ContainerNode* scope)
1128 {
1129     RefPtr<Range> range = TextIterator::rangeFromLocationAndLength(scope, index, 0, true);
1130     // Check for an invalid index. Certain editing operations invalidate indices because 
1131     // of problems with TextIteratorEmitsCharactersBetweenAllVisiblePositions.
1132     if (!range)
1133         return VisiblePosition();
1134     return VisiblePosition(range->startPosition());
1135 }
1136
1137 VisiblePosition visiblePositionForIndexUsingCharacterIterator(Node* node, int index)
1138 {
1139     ASSERT(node);
1140     if (index <= 0)
1141         return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
1142
1143     RefPtr<Range> range = Range::create(node->document());
1144     range->selectNodeContents(node, IGNORE_EXCEPTION);
1145     CharacterIterator it(*range);
1146     it.advance(index - 1);
1147     return VisiblePosition(it.atEnd() ? range->endPosition() : it.range()->endPosition(), UPSTREAM);
1148 }
1149
1150 // Determines whether two positions are visibly next to each other (first then second)
1151 // while ignoring whitespaces and unrendered nodes
1152 bool isVisiblyAdjacent(const Position& first, const Position& second)
1153 {
1154     return VisiblePosition(first) == VisiblePosition(second.upstream());
1155 }
1156
1157 // Determines whether a node is inside a range or visibly starts and ends at the boundaries of the range.
1158 // Call this function to determine whether a node is visibly fit inside selectedRange
1159 bool isNodeVisiblyContainedWithin(Node* node, const Range* selectedRange)
1160 {
1161     ASSERT(node);
1162     ASSERT(selectedRange);
1163     // If the node is inside the range, then it surely is contained within
1164     if (selectedRange->compareNode(node, IGNORE_EXCEPTION) == Range::NODE_INSIDE)
1165         return true;
1166
1167     bool startIsVisuallySame = visiblePositionBeforeNode(node) == selectedRange->startPosition();
1168     if (startIsVisuallySame && comparePositions(positionInParentAfterNode(node), selectedRange->endPosition()) < 0)
1169         return true;
1170
1171     bool endIsVisuallySame = visiblePositionAfterNode(node) == selectedRange->endPosition();
1172     if (endIsVisuallySame && comparePositions(selectedRange->startPosition(), positionInParentBeforeNode(node)) < 0)
1173         return true;
1174
1175     return startIsVisuallySame && endIsVisuallySame;
1176 }
1177
1178 bool isRenderedAsNonInlineTableImageOrHR(const Node* node)
1179 {
1180     if (!node)
1181         return false;
1182     RenderObject* renderer = node->renderer();
1183     return renderer && ((renderer->isTable() && !renderer->isInline()) || (renderer->isImage() && !renderer->isInline()) || renderer->isHR());
1184 }
1185
1186 bool areIdenticalElements(const Node* first, const Node* second)
1187 {
1188     if (!is<Element>(*first) || !is<Element>(*second))
1189         return false;
1190
1191     const Element& firstElement = downcast<Element>(*first);
1192     const Element& secondElement = downcast<Element>(*second);
1193     if (!firstElement.hasTagName(secondElement.tagQName()))
1194         return false;
1195
1196     return firstElement.hasEquivalentAttributes(&secondElement);
1197 }
1198
1199 bool isNonTableCellHTMLBlockElement(const Node* node)
1200 {
1201     return node->hasTagName(listingTag)
1202         || node->hasTagName(olTag)
1203         || node->hasTagName(preTag)
1204         || is<HTMLTableElement>(*node)
1205         || node->hasTagName(ulTag)
1206         || node->hasTagName(xmpTag)
1207         || node->hasTagName(h1Tag)
1208         || node->hasTagName(h2Tag)
1209         || node->hasTagName(h3Tag)
1210         || node->hasTagName(h4Tag)
1211         || node->hasTagName(h5Tag);
1212 }
1213
1214 Position adjustedSelectionStartForStyleComputation(const VisibleSelection& selection)
1215 {
1216     // This function is used by range style computations to avoid bugs like:
1217     // <rdar://problem/4017641> REGRESSION (Mail): you can only bold/unbold a selection starting from end of line once
1218     // It is important to skip certain irrelevant content at the start of the selection, so we do not wind up 
1219     // with a spurious "mixed" style.
1220
1221     VisiblePosition visiblePosition = selection.start();
1222     if (visiblePosition.isNull())
1223         return Position();
1224
1225     // if the selection is a caret, just return the position, since the style
1226     // behind us is relevant
1227     if (selection.isCaret())
1228         return visiblePosition.deepEquivalent();
1229
1230     // if the selection starts just before a paragraph break, skip over it
1231     if (isEndOfParagraph(visiblePosition))
1232         return visiblePosition.next().deepEquivalent().downstream();
1233
1234     // otherwise, make sure to be at the start of the first selected node,
1235     // instead of possibly at the end of the last node before the selection
1236     return visiblePosition.deepEquivalent().downstream();
1237 }
1238
1239 // FIXME: Should this be deprecated like deprecatedEnclosingBlockFlowElement is?
1240 bool isBlockFlowElement(const Node* node)
1241 {
1242     if (!node->isElementNode())
1243         return false;
1244     RenderObject* renderer = node->renderer();
1245     return renderer && renderer->isRenderBlockFlow();
1246 }
1247
1248 Element* deprecatedEnclosingBlockFlowElement(Node* node)
1249 {
1250     if (!node)
1251         return nullptr;
1252     if (isBlockFlowElement(node))
1253         return downcast<Element>(node);
1254     while ((node = node->parentNode())) {
1255         if (isBlockFlowElement(node) || is<HTMLBodyElement>(*node))
1256             return downcast<Element>(node);
1257     }
1258     return nullptr;
1259 }
1260
1261 static inline bool caretRendersInsideNode(Node* node)
1262 {
1263     return node && !isRenderedTable(node) && !editingIgnoresContent(node);
1264 }
1265
1266 RenderBlock* rendererForCaretPainting(Node* node)
1267 {
1268     if (!node)
1269         return nullptr;
1270
1271     RenderObject* renderer = node->renderer();
1272     if (!renderer)
1273         return nullptr;
1274
1275     // If caretNode is a block and caret is inside it, then caret should be painted by that block.
1276     bool paintedByBlock = is<RenderBlockFlow>(*renderer) && caretRendersInsideNode(node);
1277     return paintedByBlock ? downcast<RenderBlock>(renderer) : renderer->containingBlock();
1278 }
1279
1280 LayoutRect localCaretRectInRendererForCaretPainting(const VisiblePosition& caretPosition, RenderBlock*& caretPainter)
1281 {
1282     if (caretPosition.isNull())
1283         return LayoutRect();
1284
1285     ASSERT(caretPosition.deepEquivalent().deprecatedNode()->renderer());
1286
1287     // First compute a rect local to the renderer at the selection start.
1288     RenderObject* renderer;
1289     LayoutRect localRect = caretPosition.localCaretRect(renderer);
1290
1291     // Get the renderer that will be responsible for painting the caret
1292     // (which is either the renderer we just found, or one of its containers).
1293     caretPainter = rendererForCaretPainting(caretPosition.deepEquivalent().deprecatedNode());
1294
1295     // Compute an offset between the renderer and the caretPainter.
1296     while (renderer != caretPainter) {
1297         RenderElement* containerObject = renderer->container();
1298         if (!containerObject)
1299             return LayoutRect();
1300         localRect.move(renderer->offsetFromContainer(*containerObject, localRect.location()));
1301         renderer = containerObject;
1302     }
1303
1304     return localRect;
1305 }
1306
1307 IntRect absoluteBoundsForLocalCaretRect(RenderBlock* rendererForCaretPainting, const LayoutRect& rect)
1308 {
1309     if (!rendererForCaretPainting || rect.isEmpty())
1310         return IntRect();
1311
1312     LayoutRect localRect(rect);
1313     rendererForCaretPainting->flipForWritingMode(localRect);
1314     return rendererForCaretPainting->localToAbsoluteQuad(FloatRect(localRect)).enclosingBoundingBox();
1315 }
1316
1317 } // namespace WebCore