| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. | 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserv
ed. |
| 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. | 3 * Copyright (C) 2008, 2009, 2010, 2011 Google Inc. All rights reserved. |
| 4 * Copyright (C) 2011 Igalia S.L. | 4 * Copyright (C) 2011 Igalia S.L. |
| 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. | 5 * Copyright (C) 2011 Motorola Mobility. All rights reserved. |
| 6 * | 6 * |
| 7 * Redistribution and use in source and binary forms, with or without | 7 * Redistribution and use in source and binary forms, with or without |
| 8 * modification, are permitted provided that the following conditions | 8 * modification, are permitted provided that the following conditions |
| 9 * are met: | 9 * are met: |
| 10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 46 #include "core/dom/Range.h" | 46 #include "core/dom/Range.h" |
| 47 #include "core/editing/Editor.h" | 47 #include "core/editing/Editor.h" |
| 48 #include "core/editing/MarkupAccumulator.h" | 48 #include "core/editing/MarkupAccumulator.h" |
| 49 #include "core/editing/TextIterator.h" | 49 #include "core/editing/TextIterator.h" |
| 50 #include "core/editing/VisibleSelection.h" | 50 #include "core/editing/VisibleSelection.h" |
| 51 #include "core/editing/VisibleUnits.h" | 51 #include "core/editing/VisibleUnits.h" |
| 52 #include "core/editing/htmlediting.h" | 52 #include "core/editing/htmlediting.h" |
| 53 #include "core/frame/LocalFrame.h" | 53 #include "core/frame/LocalFrame.h" |
| 54 #include "core/html/HTMLBodyElement.h" | 54 #include "core/html/HTMLBodyElement.h" |
| 55 #include "core/html/HTMLElement.h" | 55 #include "core/html/HTMLElement.h" |
| 56 #include "core/html/HTMLTableCellElement.h" |
| 56 #include "core/html/HTMLTextFormControlElement.h" | 57 #include "core/html/HTMLTextFormControlElement.h" |
| 57 #include "core/rendering/RenderObject.h" | 58 #include "core/rendering/RenderObject.h" |
| 58 #include "platform/weborigin/KURL.h" | 59 #include "platform/weborigin/KURL.h" |
| 59 #include "wtf/StdLibExtras.h" | 60 #include "wtf/StdLibExtras.h" |
| 60 #include "wtf/text/StringBuilder.h" | 61 #include "wtf/text/StringBuilder.h" |
| 61 | 62 |
| 62 using namespace std; | 63 using namespace std; |
| 63 | 64 |
| 64 namespace WebCore { | 65 namespace WebCore { |
| 65 | 66 |
| (...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 411 } | 412 } |
| 412 } | 413 } |
| 413 } | 414 } |
| 414 } | 415 } |
| 415 | 416 |
| 416 return lastClosed; | 417 return lastClosed; |
| 417 } | 418 } |
| 418 | 419 |
| 419 static bool isHTMLBlockElement(const Node* node) | 420 static bool isHTMLBlockElement(const Node* node) |
| 420 { | 421 { |
| 421 return node->hasTagName(tdTag) | 422 ASSERT(node); |
| 422 || node->hasTagName(thTag) | 423 return isHTMLTableCellElement(*node) |
| 423 || isNonTableCellHTMLBlockElement(node); | 424 || isNonTableCellHTMLBlockElement(node); |
| 424 } | 425 } |
| 425 | 426 |
| 426 static Node* ancestorToRetainStructureAndAppearanceForBlock(Node* commonAncestor
Block) | 427 static Node* ancestorToRetainStructureAndAppearanceForBlock(Node* commonAncestor
Block) |
| 427 { | 428 { |
| 428 if (!commonAncestorBlock) | 429 if (!commonAncestorBlock) |
| 429 return 0; | 430 return 0; |
| 430 | 431 |
| 431 if (commonAncestorBlock->hasTagName(tbodyTag) || commonAncestorBlock->hasTag
Name(trTag)) { | 432 if (commonAncestorBlock->hasTagName(tbodyTag) || isHTMLTableRowElement(*comm
onAncestorBlock)) { |
| 432 ContainerNode* table = commonAncestorBlock->parentNode(); | 433 ContainerNode* table = commonAncestorBlock->parentNode(); |
| 433 while (table && !table->hasTagName(tableTag)) | 434 while (table && !isHTMLTableElement(*table)) |
| 434 table = table->parentNode(); | 435 table = table->parentNode(); |
| 435 | 436 |
| 436 return table; | 437 return table; |
| 437 } | 438 } |
| 438 | 439 |
| 439 if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) | 440 if (isNonTableCellHTMLBlockElement(commonAncestorBlock)) |
| 440 return commonAncestorBlock; | 441 return commonAncestorBlock; |
| 441 | 442 |
| 442 return 0; | 443 return 0; |
| 443 } | 444 } |
| (...skipping 20 matching lines...) Expand all Loading... |
| 464 return false; | 465 return false; |
| 465 return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone; | 466 return toCSSPrimitiveValue(value.get())->getValueID() == CSSValueNone; |
| 466 } | 467 } |
| 467 | 468 |
| 468 static bool needInterchangeNewlineAfter(const VisiblePosition& v) | 469 static bool needInterchangeNewlineAfter(const VisiblePosition& v) |
| 469 { | 470 { |
| 470 VisiblePosition next = v.next(); | 471 VisiblePosition next = v.next(); |
| 471 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); | 472 Node* upstreamNode = next.deepEquivalent().upstream().deprecatedNode(); |
| 472 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); | 473 Node* downstreamNode = v.deepEquivalent().downstream().deprecatedNode(); |
| 473 // Add an interchange newline if a paragraph break is selected and a br won'
t already be added to the markup to represent it. | 474 // Add an interchange newline if a paragraph break is selected and a br won'
t already be added to the markup to represent it. |
| 474 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(upstreamNode->ha
sTagName(brTag) && upstreamNode == downstreamNode); | 475 return isEndOfParagraph(v) && isStartOfParagraph(next) && !(isHTMLBRElement(
*upstreamNode) && upstreamNode == downstreamNode); |
| 475 } | 476 } |
| 476 | 477 |
| 477 static PassRefPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(const Node* n
ode) | 478 static PassRefPtr<EditingStyle> styleFromMatchedRulesAndInlineDecl(const Node* n
ode) |
| 478 { | 479 { |
| 479 if (!node->isHTMLElement()) | 480 if (!node->isHTMLElement()) |
| 480 return nullptr; | 481 return nullptr; |
| 481 | 482 |
| 482 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t
o untangle | 483 // FIXME: Having to const_cast here is ugly, but it is quite a bit of work t
o untangle |
| 483 // the non-const-ness of styleFromMatchedRulesForElement. | 484 // the non-const-ness of styleFromMatchedRulesForElement. |
| 484 HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); | 485 HTMLElement* element = const_cast<HTMLElement*>(toHTMLElement(node)); |
| (...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 777 tabText.append('\t'); | 778 tabText.append('\t'); |
| 778 else if (!tabText.isEmpty()) | 779 else if (!tabText.isEmpty()) |
| 779 paragraph->appendChild(createTabSpanElement(document, tabText.toStri
ng())); | 780 paragraph->appendChild(createTabSpanElement(document, tabText.toStri
ng())); |
| 780 | 781 |
| 781 first = false; | 782 first = false; |
| 782 } | 783 } |
| 783 } | 784 } |
| 784 | 785 |
| 785 bool isPlainTextMarkup(Node* node) | 786 bool isPlainTextMarkup(Node* node) |
| 786 { | 787 { |
| 788 ASSERT(node); |
| 787 if (!node->isElementNode()) | 789 if (!node->isElementNode()) |
| 788 return false; | 790 return false; |
| 789 | 791 |
| 790 Element* element = toElement(node); | 792 Element* element = toElement(node); |
| 791 if (!element->hasTagName(divTag) || !element->hasAttributes()) | 793 if (!isHTMLDivElement(*element) || !element->hasAttributes()) |
| 792 return false; | 794 return false; |
| 793 | 795 |
| 794 if (element->hasOneChild() && (element->firstChild()->isTextNode() || (eleme
nt->firstChild()->firstChild()))) | 796 if (element->hasOneChild() && (element->firstChild()->isTextNode() || (eleme
nt->firstChild()->firstChild()))) |
| 795 return true; | 797 return true; |
| 796 | 798 |
| 797 return element->hasChildCount(2) && isTabSpanTextNode(element->firstChild()-
>firstChild()) && element->lastChild()->isTextNode(); | 799 return element->hasChildCount(2) && isTabSpanTextNode(element->firstChild()-
>firstChild()) && element->lastChild()->isTextNode(); |
| 798 } | 800 } |
| 799 | 801 |
| 800 static bool shouldPreserveNewline(const Range& range) | 802 static bool shouldPreserveNewline(const Range& range) |
| 801 { | 803 { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 if (string.find('\n') == kNotFound) { | 843 if (string.find('\n') == kNotFound) { |
| 842 fillContainerFromString(fragment.get(), string); | 844 fillContainerFromString(fragment.get(), string); |
| 843 return fragment.release(); | 845 return fragment.release(); |
| 844 } | 846 } |
| 845 | 847 |
| 846 // Break string into paragraphs. Extra line breaks turn into empty paragraph
s. | 848 // Break string into paragraphs. Extra line breaks turn into empty paragraph
s. |
| 847 Node* blockNode = enclosingBlock(context->firstNode()); | 849 Node* blockNode = enclosingBlock(context->firstNode()); |
| 848 Element* block = toElement(blockNode); | 850 Element* block = toElement(blockNode); |
| 849 bool useClonesOfEnclosingBlock = blockNode | 851 bool useClonesOfEnclosingBlock = blockNode |
| 850 && blockNode->isElementNode() | 852 && blockNode->isElementNode() |
| 851 && !block->hasTagName(bodyTag) | 853 && !isHTMLBodyElement(*block) |
| 852 && !block->hasTagName(htmlTag) | 854 && !isHTMLHtmlElement(*block) |
| 853 && block != editableRootForPosition(context->startPosition()); | 855 && block != editableRootForPosition(context->startPosition()); |
| 854 bool useLineBreak = enclosingTextFormControl(context->startPosition()); | 856 bool useLineBreak = enclosingTextFormControl(context->startPosition()); |
| 855 | 857 |
| 856 Vector<String> list; | 858 Vector<String> list; |
| 857 string.split('\n', true, list); // true gets us empty strings in the list | 859 string.split('\n', true, list); // true gets us empty strings in the list |
| 858 size_t numLines = list.size(); | 860 size_t numLines = list.size(); |
| 859 for (size_t i = 0; i < numLines; ++i) { | 861 for (size_t i = 0; i < numLines; ++i) { |
| 860 const String& s = list[i]; | 862 const String& s = list[i]; |
| 861 | 863 |
| 862 RefPtr<Element> element; | 864 RefPtr<Element> element; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 903 markup.appendLiteral("<a href=\""); | 905 markup.appendLiteral("<a href=\""); |
| 904 markup.append(url.string()); | 906 markup.append(url.string()); |
| 905 markup.appendLiteral("\">"); | 907 markup.appendLiteral("\">"); |
| 906 MarkupAccumulator::appendCharactersReplacingEntities(markup, title, 0, title
.length(), EntityMaskInPCDATA); | 908 MarkupAccumulator::appendCharactersReplacingEntities(markup, title, 0, title
.length(), EntityMaskInPCDATA); |
| 907 markup.appendLiteral("</a>"); | 909 markup.appendLiteral("</a>"); |
| 908 return markup.toString(); | 910 return markup.toString(); |
| 909 } | 911 } |
| 910 | 912 |
| 911 PassRefPtr<DocumentFragment> createFragmentForInnerOuterHTML(const String& marku
p, Element* contextElement, ParserContentPolicy parserContentPolicy, const char*
method, ExceptionState& exceptionState) | 913 PassRefPtr<DocumentFragment> createFragmentForInnerOuterHTML(const String& marku
p, Element* contextElement, ParserContentPolicy parserContentPolicy, const char*
method, ExceptionState& exceptionState) |
| 912 { | 914 { |
| 913 Document& document = contextElement->hasTagName(templateTag) ? contextElemen
t->document().ensureTemplateDocument() : contextElement->document(); | 915 ASSERT(contextElement); |
| 916 Document& document = isHTMLTemplateElement(*contextElement) ? contextElement
->document().ensureTemplateDocument() : contextElement->document(); |
| 914 RefPtr<DocumentFragment> fragment = DocumentFragment::create(document); | 917 RefPtr<DocumentFragment> fragment = DocumentFragment::create(document); |
| 915 | 918 |
| 916 if (document.isHTMLDocument()) { | 919 if (document.isHTMLDocument()) { |
| 917 fragment->parseHTML(markup, contextElement, parserContentPolicy); | 920 fragment->parseHTML(markup, contextElement, parserContentPolicy); |
| 918 return fragment; | 921 return fragment; |
| 919 } | 922 } |
| 920 | 923 |
| 921 bool wasValid = fragment->parseXML(markup, contextElement, parserContentPoli
cy); | 924 bool wasValid = fragment->parseXML(markup, contextElement, parserContentPoli
cy); |
| 922 if (!wasValid) { | 925 if (!wasValid) { |
| 923 exceptionState.throwDOMException(SyntaxError, "The provided markup is in
valid XML, and therefore cannot be inserted into an XML document."); | 926 exceptionState.throwDOMException(SyntaxError, "The provided markup is in
valid XML, and therefore cannot be inserted into an XML document."); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 if (!fragment) | 977 if (!fragment) |
| 975 return nullptr; | 978 return nullptr; |
| 976 | 979 |
| 977 // We need to pop <html> and <body> elements and remove <head> to | 980 // We need to pop <html> and <body> elements and remove <head> to |
| 978 // accommodate folks passing complete HTML documents to make the | 981 // accommodate folks passing complete HTML documents to make the |
| 979 // child of an element. | 982 // child of an element. |
| 980 | 983 |
| 981 RefPtr<Node> nextNode; | 984 RefPtr<Node> nextNode; |
| 982 for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) { | 985 for (RefPtr<Node> node = fragment->firstChild(); node; node = nextNode) { |
| 983 nextNode = node->nextSibling(); | 986 nextNode = node->nextSibling(); |
| 984 if (node->hasTagName(htmlTag) || node->hasTagName(headTag) || node->hasT
agName(bodyTag)) { | 987 if (isHTMLHtmlElement(*node) || isHTMLHeadElement(*node) || isHTMLBodyEl
ement(*node)) { |
| 985 HTMLElement* element = toHTMLElement(node); | 988 HTMLElement* element = toHTMLElement(node); |
| 986 if (Node* firstChild = element->firstChild()) | 989 if (Node* firstChild = element->firstChild()) |
| 987 nextNode = firstChild; | 990 nextNode = firstChild; |
| 988 removeElementPreservingChildren(fragment, element); | 991 removeElementPreservingChildren(fragment, element); |
| 989 } | 992 } |
| 990 } | 993 } |
| 991 return fragment.release(); | 994 return fragment.release(); |
| 992 } | 995 } |
| 993 | 996 |
| 994 void replaceChildrenWithFragment(ContainerNode* container, PassRefPtr<DocumentFr
agment> fragment, ExceptionState& exceptionState) | 997 void replaceChildrenWithFragment(ContainerNode* container, PassRefPtr<DocumentFr
agment> fragment, ExceptionState& exceptionState) |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 return; | 1051 return; |
| 1049 | 1052 |
| 1050 RefPtr<Text> textNode = toText(node.get()); | 1053 RefPtr<Text> textNode = toText(node.get()); |
| 1051 RefPtr<Text> textNext = toText(next); | 1054 RefPtr<Text> textNext = toText(next); |
| 1052 textNode->appendData(textNext->data()); | 1055 textNode->appendData(textNext->data()); |
| 1053 if (textNext->parentNode()) // Might have been removed by mutation event. | 1056 if (textNext->parentNode()) // Might have been removed by mutation event. |
| 1054 textNext->remove(exceptionState); | 1057 textNext->remove(exceptionState); |
| 1055 } | 1058 } |
| 1056 | 1059 |
| 1057 } | 1060 } |
| OLD | NEW |