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 |