diff options
| author | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
|---|---|---|
| committer | The Android Open Source Project <initial-contribution@android.com> | 2008-10-21 07:00:00 -0700 |
| commit | 9364f22aed35e1a1e9d07c121510f80be3ab0502 (patch) | |
| tree | d49911209b132da58d838efa852daf28d516df21 /WebCore/editing | |
| parent | 87eb0cb35bad8784770ebc807e6c982432e47107 (diff) | |
| download | external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.zip external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.tar.gz external_webkit-9364f22aed35e1a1e9d07c121510f80be3ab0502.tar.bz2 | |
Initial Contribution
Diffstat (limited to 'WebCore/editing')
| -rw-r--r-- | WebCore/editing/DeleteSelectionCommand.cpp | 37 | ||||
| -rw-r--r-- | WebCore/editing/EditCommand.cpp | 3 | ||||
| -rw-r--r-- | WebCore/editing/HTMLInterchange.cpp | 69 | ||||
| -rw-r--r-- | WebCore/editing/HTMLInterchange.h | 6 | ||||
| -rw-r--r-- | WebCore/editing/ReplaceSelectionCommand.cpp | 233 | ||||
| -rw-r--r-- | WebCore/editing/ReplaceSelectionCommand.h | 3 | ||||
| -rw-r--r-- | WebCore/editing/Selection.cpp | 10 | ||||
| -rw-r--r-- | WebCore/editing/SelectionController.cpp | 18 | ||||
| -rw-r--r-- | WebCore/editing/TextIterator.cpp | 20 | ||||
| -rw-r--r-- | WebCore/editing/TextIterator.h | 14 | ||||
| -rw-r--r-- | WebCore/editing/TypingCommand.cpp | 2 | ||||
| -rw-r--r-- | WebCore/editing/VisiblePosition.cpp | 6 | ||||
| -rw-r--r-- | WebCore/editing/htmlediting.cpp | 10 | ||||
| -rw-r--r-- | WebCore/editing/markup.cpp | 220 |
14 files changed, 276 insertions, 375 deletions
diff --git a/WebCore/editing/DeleteSelectionCommand.cpp b/WebCore/editing/DeleteSelectionCommand.cpp index 28eca34..6bedd69 100644 --- a/WebCore/editing/DeleteSelectionCommand.cpp +++ b/WebCore/editing/DeleteSelectionCommand.cpp @@ -120,7 +120,7 @@ void DeleteSelectionCommand::initializeStartEnd(Position& start, Position& end) if (!m_expandForSpecialElements) return; - while (1) { + while (VisiblePosition(start) == m_selectionToDelete.visibleStart() && VisiblePosition(end) == m_selectionToDelete.visibleEnd()) { startSpecialContainer = 0; endSpecialContainer = 0; @@ -129,9 +129,6 @@ void DeleteSelectionCommand::initializeStartEnd(Position& start, Position& end) if (!startSpecialContainer && !endSpecialContainer) break; - - if (VisiblePosition(start) != m_selectionToDelete.visibleStart() || VisiblePosition(end) != m_selectionToDelete.visibleEnd()) - break; // If we're going to expand to include the startSpecialContainer, it must be fully selected. if (startSpecialContainer && !endSpecialContainer && Range::compareBoundaryPoints(positionAfterNode(startSpecialContainer), end) > -1) @@ -233,16 +230,6 @@ void DeleteSelectionCommand::initializePositionData() void DeleteSelectionCommand::saveTypingStyleState() { - // A common case is deleting characters that are all from the same text node. In - // that case, the style at the start of the selection before deletion will be the - // same as the style at the start of the selection after deletion (since those - // two positions will be identical). Therefore there is no need to save the - // typing style at the start of the selection, nor is there a reason to - // compute the style at the start of the selection after deletion (see the - // early return in calculateTypingStyleAfterDelete). - if (m_upstreamStart.node() == m_downstreamEnd.node() && m_upstreamStart.node()->isTextNode()) - return; - // Figure out the typing style in effect before the delete is done. // FIXME: Improve typing style. // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement @@ -613,9 +600,6 @@ void DeleteSelectionCommand::removePreviouslySelectedEmptyTableRows() void DeleteSelectionCommand::calculateTypingStyleAfterDelete(Node *insertedPlaceholder) { - if (!m_typingStyle) - return; - // Compute the difference between the style before the delete and the style now // after the delete has been done. Set this style on the frame, so other editing // commands being composed with this one will work, and also cache it on the command, @@ -664,21 +648,12 @@ void DeleteSelectionCommand::clearTransientState() void DeleteSelectionCommand::saveFullySelectedAnchor() { - // If deleting an anchor element, save it away so that it can be restored + // If we're deleting an entire anchor element, save it away so that it can be restored // when the user begins entering text. - - Position start = m_selectionToDelete.start(); - Node* startAnchor = enclosingNodeWithTag(start.downstream(), aTag); - if (!startAnchor) - return; - - Position end = m_selectionToDelete.end(); - Node* endAnchor = enclosingNodeWithTag(end.upstream(), aTag); - if (startAnchor != endAnchor) - return; - - VisiblePosition visibleStart(m_selectionToDelete.visibleStart()); - VisiblePosition visibleEnd(m_selectionToDelete.visibleEnd()); + VisiblePosition visibleStart = m_selectionToDelete.visibleStart(); + VisiblePosition visibleEnd = m_selectionToDelete.visibleEnd(); + Node* startAnchor = enclosingNodeWithTag(visibleStart.deepEquivalent().downstream(), aTag); + Node* endAnchor = enclosingNodeWithTag(visibleEnd.deepEquivalent().upstream(), aTag); Node* beforeStartAnchor = enclosingNodeWithTag(visibleStart.previous().deepEquivalent().downstream(), aTag); Node* afterEndAnchor = enclosingNodeWithTag(visibleEnd.next().deepEquivalent().upstream(), aTag); diff --git a/WebCore/editing/EditCommand.cpp b/WebCore/editing/EditCommand.cpp index a7c7ed0..7a5d752 100644 --- a/WebCore/editing/EditCommand.cpp +++ b/WebCore/editing/EditCommand.cpp @@ -44,8 +44,7 @@ namespace WebCore { using namespace EventNames; EditCommand::EditCommand(Document* document) - : RefCounted<EditCommand>(0) - , m_document(document) + : m_document(document) , m_parent(0) { ASSERT(m_document); diff --git a/WebCore/editing/HTMLInterchange.cpp b/WebCore/editing/HTMLInterchange.cpp index 024ac9f..e17f32e 100644 --- a/WebCore/editing/HTMLInterchange.cpp +++ b/WebCore/editing/HTMLInterchange.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -27,6 +27,7 @@ #include "HTMLInterchange.h" #include "CharacterNames.h" +#include "Document.h" #include "Text.h" #include "TextIterator.h" @@ -34,14 +35,14 @@ namespace WebCore { namespace { -String convertedSpaceString() +DeprecatedString convertedSpaceString() { - static String convertedSpaceString; - if (convertedSpaceString.isNull()) { + static DeprecatedString convertedSpaceString; + if (convertedSpaceString.length() == 0) { convertedSpaceString = "<span class=\""; convertedSpaceString += AppleConvertedSpace; convertedSpaceString += "\">"; - convertedSpaceString.append(noBreakSpace); + convertedSpaceString += DeprecatedChar(noBreakSpace); convertedSpaceString += "</span>"; } return convertedSpaceString; @@ -49,63 +50,67 @@ String convertedSpaceString() } // end anonymous namespace -String convertHTMLTextToInterchangeFormat(const String& in, const Text* node) +DeprecatedString convertHTMLTextToInterchangeFormat(const DeprecatedString& in, const Text* node) { // Assume all the text comes from node. if (node->renderer() && node->renderer()->style()->preserveNewline()) return in; + + DeprecatedString s; - Vector<UChar> s; - - unsigned i = 0; - unsigned consumed = 0; + unsigned int i = 0; + unsigned int consumed = 0; while (i < in.length()) { consumed = 1; - if (isCollapsibleWhitespace(in[i])) { + if (isCollapsibleWhitespace(in[i].unicode())) { // count number of adjoining spaces - unsigned j = i + 1; - while (j < in.length() && isCollapsibleWhitespace(in[j])) + unsigned int j = i + 1; + while (j < in.length() && isCollapsibleWhitespace(in[j].unicode())) j++; - unsigned count = j - i; + unsigned int count = j - i; consumed = count; while (count) { - unsigned add = count % 3; + unsigned int add = count % 3; switch (add) { case 0: - append(s, convertedSpaceString()); - s.append(' '); - append(s, convertedSpaceString()); + s += convertedSpaceString(); + s += ' '; + s += convertedSpaceString(); add = 3; break; case 1: if (i == 0 || i + 1 == in.length()) // at start or end of string - append(s, convertedSpaceString()); + s += convertedSpaceString(); else - s.append(' '); + s += ' '; break; case 2: if (i == 0) { // at start of string - append(s, convertedSpaceString()); - s.append(' '); - } else if (i + 2 == in.length()) { + s += convertedSpaceString(); + s += ' '; + } + else if (i + 2 == in.length()) { // at end of string - append(s, convertedSpaceString()); - append(s, convertedSpaceString()); - } else { - append(s, convertedSpaceString()); - s.append(' '); + s += convertedSpaceString(); + s += convertedSpaceString(); + } + else { + s += convertedSpaceString(); + s += ' '; } break; } count -= add; } - } else - s.append(in[i]); + } + else { + s += in[i]; + } i += consumed; } - return String::adopt(s); + return s; } -} // namespace WebCore +} diff --git a/WebCore/editing/HTMLInterchange.h b/WebCore/editing/HTMLInterchange.h index 3b68efb..c840231 100644 --- a/WebCore/editing/HTMLInterchange.h +++ b/WebCore/editing/HTMLInterchange.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -28,7 +28,7 @@ namespace WebCore { -class String; +class DeprecatedString; class Text; #define AppleInterchangeNewline "Apple-interchange-newline" @@ -39,7 +39,7 @@ class Text; enum EAnnotateForInterchange { DoNotAnnotateForInterchange, AnnotateForInterchange }; -String convertHTMLTextToInterchangeFormat(const String&, const Text*); +DeprecatedString convertHTMLTextToInterchangeFormat(const DeprecatedString&, const Text*); } diff --git a/WebCore/editing/ReplaceSelectionCommand.cpp b/WebCore/editing/ReplaceSelectionCommand.cpp index 1f66de4..a110480 100644 --- a/WebCore/editing/ReplaceSelectionCommand.cpp +++ b/WebCore/editing/ReplaceSelectionCommand.cpp @@ -29,7 +29,6 @@ #include "ApplyStyleCommand.h" #include "BeforeTextInsertedEvent.h" #include "CSSComputedStyleDeclaration.h" -#include "CSSProperty.h" #include "CSSPropertyNames.h" #include "CSSValueKeywords.h" #include "Document.h" @@ -414,11 +413,84 @@ void ReplaceSelectionCommand::removeUnrenderedTextNodesAtEnds() } } +void ReplaceSelectionCommand::removeRedundantStyles(Node* mailBlockquoteEnclosingSelectionStart) +{ + // There's usually a top level style span that holds the document's default style, push it down. + Node* node = m_firstNodeInserted.get(); + if (isStyleSpan(node) && mailBlockquoteEnclosingSelectionStart) { + // Calculate the document default style. + RefPtr<CSSMutableStyleDeclaration> blockquoteStyle = Position(mailBlockquoteEnclosingSelectionStart, 0).computedStyle()->copyInheritableProperties(); + RefPtr<CSSMutableStyleDeclaration> spanStyle = static_cast<HTMLElement*>(node)->inlineStyleDecl(); + spanStyle->merge(blockquoteStyle.get()); + } + + // Compute and save the non-redundant styles for all HTML elements. + // Don't do any mutation here, because that would cause the diffs to trigger layouts. + Vector<RefPtr<CSSMutableStyleDeclaration> > styles; + Vector<RefPtr<HTMLElement> > elements; + for (node = m_firstNodeInserted.get(); node; node = node->traverseNextNode()) { + if (node->isHTMLElement() && isStyleSpan(node)) { + elements.append(static_cast<HTMLElement*>(node)); + + RefPtr<CSSMutableStyleDeclaration> parentStyle = computedStyle(node->parentNode())->copyInheritableProperties(); + RefPtr<CSSMutableStyleDeclaration> style = computedStyle(node)->copyInheritableProperties(); + parentStyle->diff(style.get()); + + // Remove any inherited block properties that are now in the span's style. This cuts out meaningless properties + // and prevents properties from magically affecting blocks later if the style is cloned for a new block element + // during a future editing operation. + style->removeBlockProperties(); + + styles.append(style.release()); + } + if (node == m_lastLeafInserted) + break; + } + + size_t count = styles.size(); + for (size_t i = 0; i < count; ++i) { + HTMLElement* element = elements[i].get(); + + // Handle case where the element was already removed by earlier processing. + // It's possible this no longer occurs, but it did happen in an earlier version + // that processed elements in a less-determistic order, and I can't prove it + // does not occur. + if (!element->inDocument()) + continue; + + // Remove empty style spans. + if (isStyleSpan(element) && !element->hasChildNodes()) { + removeNodeAndPruneAncestors(element); + continue; + } + + // Remove redundant style tags and style spans. + CSSMutableStyleDeclaration* style = styles[i].get(); + if (style->length() == 0 + && (isStyleSpan(element) + || element->hasTagName(bTag) + || element->hasTagName(fontTag) + || element->hasTagName(iTag) + || element->hasTagName(uTag))) { + removeNodePreservingChildren(element); + continue; + } + + // Clear redundant styles from elements. + CSSMutableStyleDeclaration* inlineStyleDecl = element->inlineStyleDecl(); + if (inlineStyleDecl) { + CSSComputedStyleDeclaration::removeComputedInheritablePropertiesFrom(inlineStyleDecl); + inlineStyleDecl->merge(style, true); + setNodeAttribute(element, styleAttr, inlineStyleDecl->cssText()); + } + } +} + void ReplaceSelectionCommand::handlePasteAsQuotationNode() { Node* node = m_firstNodeInserted.get(); if (isMailPasteAsQuotationNode(node)) - removeNodeAttribute(static_cast<Element*>(node), classAttr); + static_cast<Element*>(node)->setAttribute(classAttr, ""); } VisiblePosition ReplaceSelectionCommand::positionAtEndOfInsertedContent() @@ -436,146 +508,6 @@ VisiblePosition ReplaceSelectionCommand::positionAtStartOfInsertedContent() return VisiblePosition(nextCandidate(positionBeforeNode(m_firstNodeInserted.get()))); } -// Remove style spans before insertion if they are unnecessary. It's faster because we'll -// avoid doing a layout. -static bool handleStyleSpansBeforeInsertion(ReplacementFragment& fragment, const Position& insertionPos) -{ - Node* topNode = fragment.firstChild(); - - // Handling this case is more complicated (see handleStyleSpans) and doesn't receive the optimization. - if (isMailPasteAsQuotationNode(topNode)) - return false; - - // Either there are no style spans in the fragment or a WebKit client has added content to the fragment - // before inserting it. Look for and handle style spans after insertion. - if (!isStyleSpan(topNode)) - return false; - - Node* sourceDocumentStyleSpan = topNode; - RefPtr<Node> copiedRangeStyleSpan = sourceDocumentStyleSpan->firstChild(); - - RefPtr<CSSMutableStyleDeclaration> styleAtInsertionPos = rangeCompliantEquivalent(insertionPos).computedStyle()->copyInheritableProperties(); - String styleText = styleAtInsertionPos->cssText(); - - if (styleText == static_cast<Element*>(sourceDocumentStyleSpan)->getAttribute(styleAttr)) { - fragment.removeNodePreservingChildren(sourceDocumentStyleSpan); - if (!isStyleSpan(copiedRangeStyleSpan.get())) - return true; - } - - if (isStyleSpan(copiedRangeStyleSpan.get()) && styleText == static_cast<Element*>(copiedRangeStyleSpan.get())->getAttribute(styleAttr)) { - fragment.removeNodePreservingChildren(copiedRangeStyleSpan.get()); - return true; - } - - return false; -} - -// At copy time, WebKit wraps copied content in a span that contains the source document's -// default styles. If the copied Range inherits any other styles from its ancestors, we put -// those styles on a second span. -// This function removes redundant styles from those spans, and removes the spans if all their -// styles are redundant. -// We should remove the Apple-style-span class when we're done, see <rdar://problem/5685600>. -// We should remove styles from spans that are overridden by all of their children, either here -// or at copy time. -void ReplaceSelectionCommand::handleStyleSpans() -{ - Node* sourceDocumentStyleSpan = 0; - Node* copiedRangeStyleSpan = 0; - // The style span that contains the source document's default style should be at - // the top of the fragment, but Mail sometimes adds a wrapper (for Paste As Quotation), - // so search for the top level style span instead of assuming it's at the top. - for (Node* node = m_firstNodeInserted.get(); node; node = node->traverseNextNode()) { - if (isStyleSpan(node)) { - sourceDocumentStyleSpan = node; - // If the copied Range's common ancestor had user applied inheritable styles - // on it, they'll be on a second style span, just below the one that holds the - // document defaults. - if (isStyleSpan(node->firstChild())) - copiedRangeStyleSpan = node->firstChild(); - break; - } - } - - // There might not be any style spans if we're pasting from another application or if - // we are here because of a document.execCommand("InsertHTML", ...) call. - if (!sourceDocumentStyleSpan) - return; - - RefPtr<CSSMutableStyleDeclaration> sourceDocumentStyle = static_cast<HTMLElement*>(sourceDocumentStyleSpan)->getInlineStyleDecl()->copy(); - Node* context = sourceDocumentStyleSpan->parentNode(); - - // If Mail wraps the fragment with a Paste as Quotation blockquote, styles from that element are - // allowed to override those from the source document, see <rdar://problem/4930986>. - if (isMailPasteAsQuotationNode(context)) { - RefPtr<CSSMutableStyleDeclaration> blockquoteStyle = computedStyle(context)->copyInheritableProperties(); - RefPtr<CSSMutableStyleDeclaration> parentStyle = computedStyle(context->parentNode())->copyInheritableProperties(); - parentStyle->diff(blockquoteStyle.get()); - - DeprecatedValueListConstIterator<CSSProperty> end; - for (DeprecatedValueListConstIterator<CSSProperty> it = blockquoteStyle->valuesIterator(); it != end; ++it) { - const CSSProperty& property = *it; - sourceDocumentStyle->removeProperty(property.id()); - } - - context = context->parentNode(); - } - - RefPtr<CSSMutableStyleDeclaration> contextStyle = computedStyle(context)->copyInheritableProperties(); - String contextStyleText = contextStyle->cssText(); - String sourceDocumentStyleText = sourceDocumentStyle->cssText(); - contextStyle->diff(sourceDocumentStyle.get()); - - // Remove block properties in the span's style. This prevents properties that probably have no effect - // currently from affecting blocks later if the style is cloned for a new block element during a future - // editing operation. - // FIXME: They *can* have an effect currently if blocks beneath the style span aren't individually marked - // with block styles by the editing engine used to style them. WebKit doesn't do this, but others might. - sourceDocumentStyle->removeBlockProperties(); - - // The styles on sourceDocumentStyleSpan are all redundant, and there is no copiedRangeStyleSpan - // to consider. We're finished. - if (sourceDocumentStyle->length() == 0 && !copiedRangeStyleSpan) { - removeNodePreservingChildren(sourceDocumentStyleSpan); - return; - } - - // There are non-redundant styles on sourceDocumentStyleSpan, but there is no - // copiedRangeStyleSpan. Clear the redundant styles from sourceDocumentStyleSpan - // and return. - if (sourceDocumentStyle->length() > 0 && !copiedRangeStyleSpan) { - setNodeAttribute(static_cast<Element*>(sourceDocumentStyleSpan), styleAttr, sourceDocumentStyle->cssText()); - return; - } - - RefPtr<CSSMutableStyleDeclaration> copiedRangeStyle = static_cast<HTMLElement*>(copiedRangeStyleSpan)->getInlineStyleDecl()->copy(); - - // We're going to put sourceDocumentStyleSpan's non-redundant styles onto copiedRangeStyleSpan, - // as long as they aren't overridden by ones on copiedRangeStyleSpan. - sourceDocumentStyle->merge(copiedRangeStyle.get(), true); - copiedRangeStyle = sourceDocumentStyle; - - removeNodePreservingChildren(sourceDocumentStyleSpan); - - // Remove redundant styles. - context = copiedRangeStyleSpan->parentNode(); - contextStyle = computedStyle(context)->copyInheritableProperties(); - contextStyle->diff(copiedRangeStyle.get()); - - // See the comments above about removing block properties. - copiedRangeStyle->removeBlockProperties(); - - // All the styles on copiedRangeStyleSpan are redundant, remove it. - if (copiedRangeStyle->length() == 0) { - removeNodePreservingChildren(copiedRangeStyleSpan); - return; - } - - // Clear the redundant styles from the span's style attribute. - setNodeAttribute(static_cast<Element*>(copiedRangeStyleSpan), styleAttr, copiedRangeStyle->cssText()); -} - void ReplaceSelectionCommand::doApply() { Selection selection = endingSelection(); @@ -597,6 +529,7 @@ void ReplaceSelectionCommand::doApply() bool selectionEndWasEndOfParagraph = isEndOfParagraph(visibleEnd); bool selectionStartWasStartOfParagraph = isStartOfParagraph(visibleStart); + Node* mailBlockquoteEnclosingSelectionStart = nearestMailBlockquote(visibleStart.deepEquivalent().node()); Node* startBlock = enclosingBlock(visibleStart.deepEquivalent().node()); @@ -680,9 +613,16 @@ void ReplaceSelectionCommand::doApply() // FIXME: Improve typing style. // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement frame->clearTypingStyle(); - setTypingStyle(0); - - bool handledStyleSpans = handleStyleSpansBeforeInsertion(fragment, insertionPos); + setTypingStyle(0); + + // Remove the top level style span if its unnecessary before inserting it into the document, its faster. + RefPtr<CSSMutableStyleDeclaration> styleAtInsertionPos = insertionPos.computedStyle()->copyInheritableProperties(); + if (isStyleSpan(fragment.firstChild())) { + Node* styleSpan = fragment.firstChild(); + String styleText = static_cast<Element*>(styleSpan)->getAttribute(styleAttr); + if (styleText == styleAtInsertionPos->cssText()) + fragment.removeNodePreservingChildren(styleSpan); + } // We're finished if there is nothing to add. if (fragment.isEmpty() || !fragment.firstChild()) @@ -718,8 +658,7 @@ void ReplaceSelectionCommand::doApply() negateStyleRulesThatAffectAppearance(); - if (!handledStyleSpans) - handleStyleSpans(); + removeRedundantStyles(mailBlockquoteEnclosingSelectionStart); if (!m_firstNodeInserted) return; diff --git a/WebCore/editing/ReplaceSelectionCommand.h b/WebCore/editing/ReplaceSelectionCommand.h index d900c71..679a90e 100644 --- a/WebCore/editing/ReplaceSelectionCommand.h +++ b/WebCore/editing/ReplaceSelectionCommand.h @@ -92,7 +92,8 @@ private: void removeUnrenderedTextNodesAtEnds(); void negateStyleRulesThatAffectAppearance(); - void handleStyleSpans(); + void removeRedundantStyles(Node*); + void handlePasteAsQuotationNode(); virtual void removeNodePreservingChildren(Node*); diff --git a/WebCore/editing/Selection.cpp b/WebCore/editing/Selection.cpp index d29ac40..32f6500 100644 --- a/WebCore/editing/Selection.cpp +++ b/WebCore/editing/Selection.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "Selection.h" -#include "CString.h" #include "Document.h" #include "Element.h" #include "htmlediting.h" @@ -34,7 +33,6 @@ #include "visible_units.h" #include "Range.h" #include <wtf/Assertions.h> -#include <stdio.h> namespace WebCore { @@ -526,13 +524,13 @@ void Selection::debugPosition() const if (m_start == m_end) { Position pos = m_start; - fprintf(stderr, "pos: %s %p:%d\n", pos.node()->nodeName().utf8().data(), pos.node(), pos.offset()); + fprintf(stderr, "pos: %s %p:%d\n", pos.node()->nodeName().deprecatedString().latin1(), pos.node(), pos.offset()); } else { Position pos = m_start; - fprintf(stderr, "start: %s %p:%d\n", pos.node()->nodeName().utf8().data(), pos.node(), pos.offset()); + fprintf(stderr, "start: %s %p:%d\n", pos.node()->nodeName().deprecatedString().latin1(), pos.node(), pos.offset()); fprintf(stderr, "-----------------------------------\n"); pos = m_end; - fprintf(stderr, "end: %s %p:%d\n", pos.node()->nodeName().utf8().data(), pos.node(), pos.offset()); + fprintf(stderr, "end: %s %p:%d\n", pos.node()->nodeName().deprecatedString().latin1(), pos.node(), pos.offset()); fprintf(stderr, "-----------------------------------\n"); } @@ -559,7 +557,7 @@ void Selection::formatForDebugger(char* buffer, unsigned length) const result += s; } - strncpy(buffer, result.utf8().data(), length - 1); + strncpy(buffer, result.deprecatedString().latin1(), length - 1); } void Selection::showTreeForThis() const diff --git a/WebCore/editing/SelectionController.cpp b/WebCore/editing/SelectionController.cpp index cd6286a..6e1d6bf 100644 --- a/WebCore/editing/SelectionController.cpp +++ b/WebCore/editing/SelectionController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004 Apple Computer, Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -26,7 +26,6 @@ #include "config.h" #include "SelectionController.h" -#include "CString.h" #include "DeleteSelectionCommand.h" #include "Document.h" #include "Editor.h" @@ -51,7 +50,6 @@ #include "TypingCommand.h" #include "htmlediting.h" #include "visible_units.h" -#include <stdio.h> #define EDIT_DEBUG 0 @@ -793,7 +791,7 @@ void SelectionController::debugRenderer(RenderObject *r, bool selected) const { if (r->node()->isElementNode()) { Element *element = static_cast<Element *>(r->node()); - fprintf(stderr, "%s%s\n", selected ? "==> " : " ", element->localName().string().utf8().data()); + fprintf(stderr, "%s%s\n", selected ? "==> " : " ", element->localName().deprecatedString().latin1()); } else if (r->isText()) { RenderText* textRenderer = static_cast<RenderText*>(r); @@ -803,7 +801,7 @@ void SelectionController::debugRenderer(RenderObject *r, bool selected) const } static const int max = 36; - String text = textRenderer->text(); + DeprecatedString text = String(textRenderer->text()).deprecatedString(); int textLength = text.length(); if (selected) { int offset = 0; @@ -814,9 +812,9 @@ void SelectionController::debugRenderer(RenderObject *r, bool selected) const int pos; InlineTextBox *box = textRenderer->findNextInlineTextBox(offset, pos); - text = text.substring(box->m_start, box->m_len); + text = text.mid(box->m_start, box->m_len); - String show; + DeprecatedString show; int mid = max / 2; int caret = 0; @@ -834,7 +832,7 @@ void SelectionController::debugRenderer(RenderObject *r, bool selected) const // enough characters on each side else if (pos - mid >= 0 && pos + mid <= textLength) { - show = "..." + text.substring(pos - mid + 3, max - 6) + "..."; + show = "..." + text.mid(pos - mid + 3, max - 6) + "..."; caret = mid; } @@ -846,7 +844,7 @@ void SelectionController::debugRenderer(RenderObject *r, bool selected) const show.replace('\n', ' '); show.replace('\r', ' '); - fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.utf8().data(), pos); + fprintf(stderr, "==> #text : \"%s\" at offset %d\n", show.latin1(), pos); fprintf(stderr, " "); for (int i = 0; i < caret; i++) fprintf(stderr, " "); @@ -857,7 +855,7 @@ void SelectionController::debugRenderer(RenderObject *r, bool selected) const text = text.left(max - 3) + "..."; else text = text.left(max); - fprintf(stderr, " #text : \"%s\"\n", text.utf8().data()); + fprintf(stderr, " #text : \"%s\"\n", text.latin1()); } } } diff --git a/WebCore/editing/TextIterator.cpp b/WebCore/editing/TextIterator.cpp index 233361e..c6f1928 100644 --- a/WebCore/editing/TextIterator.cpp +++ b/WebCore/editing/TextIterator.cpp @@ -962,17 +962,17 @@ void CharacterIterator::advance(int count) m_runOffset = 0; } -String CharacterIterator::string(int numChars) +DeprecatedString CharacterIterator::string(int numChars) { - Vector<UChar> result; - result.reserveCapacity(numChars); + DeprecatedString result; + result.reserve(numChars); while (numChars > 0 && !atEnd()) { int runSize = min(numChars, length()); - result.append(characters(), runSize); + result.append(reinterpret_cast<const DeprecatedChar*>(characters()), runSize); numChars -= runSize; advance(runSize); } - return String::adopt(result); + return result; } // -------- @@ -1001,7 +1001,7 @@ WordAwareIterator::WordAwareIterator(const Range *r) void WordAwareIterator::advance() { m_previousText = 0; - m_buffer.clear(); // toss any old buffer we built up + m_buffer = ""; // toss any old buffer we built up // If last time we did a look-ahead, start with that looked-ahead chunk now if (!m_didLookAhead) { @@ -1038,10 +1038,10 @@ void WordAwareIterator::advance() if (m_buffer.isEmpty()) { // Start gobbling chunks until we get to a suitable stopping point - m_buffer.append(m_previousText, m_previousLength); + m_buffer.append(reinterpret_cast<const DeprecatedChar*>(m_previousText), m_previousLength); m_previousText = 0; } - m_buffer.append(m_textIterator.characters(), m_textIterator.length()); + m_buffer.append(reinterpret_cast<const DeprecatedChar*>(m_textIterator.characters()), m_textIterator.length()); int exception = 0; m_range->setEnd(m_textIterator.range()->endContainer(exception), m_textIterator.range()->endOffset(exception), exception); } @@ -1050,7 +1050,7 @@ void WordAwareIterator::advance() int WordAwareIterator::length() const { if (!m_buffer.isEmpty()) - return m_buffer.size(); + return m_buffer.length(); if (m_previousText) return m_previousLength; return m_textIterator.length(); @@ -1059,7 +1059,7 @@ int WordAwareIterator::length() const const UChar* WordAwareIterator::characters() const { if (!m_buffer.isEmpty()) - return m_buffer.data(); + return reinterpret_cast<const UChar*>(m_buffer.unicode()); if (m_previousText) return m_previousText; return m_textIterator.characters(); diff --git a/WebCore/editing/TextIterator.h b/WebCore/editing/TextIterator.h index 56f42be..5f36468 100644 --- a/WebCore/editing/TextIterator.h +++ b/WebCore/editing/TextIterator.h @@ -26,6 +26,7 @@ #ifndef TextIterator_h #define TextIterator_h +#include "DeprecatedString.h" #include "InlineTextBox.h" #include "Range.h" #include <wtf/Vector.h> @@ -33,7 +34,8 @@ namespace WebCore { // FIXME: Can't really answer this question correctly without knowing the white-space mode. -// FIXME: Move this somewhere else in the editing directory. It doesn't belong here. +// FIXME: Move this along with the white-space position functions above +// somewhere else in the editing directory. It doesn't belong here. inline bool isCollapsibleWhitespace(UChar c) { switch (c) { @@ -53,7 +55,8 @@ PassRefPtr<Range> findPlainText(const Range*, const String&, bool forward, bool // at points where replaced elements break up the text flow. The text comes back in // chunks so as to optimize for performance of the iteration. -class TextIterator { +class TextIterator +{ public: TextIterator(); explicit TextIterator(const Range*, bool emitCharactersBetweenAllVisiblePositions = false); @@ -132,7 +135,8 @@ private: // Iterates through the DOM range, returning all the text, and 0-length boundaries // at points where replaced elements break up the text flow. The text comes back in // chunks so as to optimize for performance of the iteration. -class SimplifiedBackwardsTextIterator { +class SimplifiedBackwardsTextIterator +{ public: SimplifiedBackwardsTextIterator(); explicit SimplifiedBackwardsTextIterator(const Range *); @@ -198,7 +202,7 @@ public: int length() const { return m_textIterator.length() - m_runOffset; } const UChar* characters() const { return m_textIterator.characters() + m_runOffset; } - String string(int numChars); + DeprecatedString string(int numChars); int characterOffset() const { return m_offset; } PassRefPtr<Range> range() const; @@ -233,7 +237,7 @@ private: int m_previousLength; // many chunks from textIterator concatenated - Vector<UChar> m_buffer; + DeprecatedString m_buffer; // Did we have to look ahead in the textIterator to confirm the current chunk? bool m_didLookAhead; diff --git a/WebCore/editing/TypingCommand.cpp b/WebCore/editing/TypingCommand.cpp index 2c0518e..f480c07 100644 --- a/WebCore/editing/TypingCommand.cpp +++ b/WebCore/editing/TypingCommand.cpp @@ -280,8 +280,6 @@ EditAction TypingCommand::editingAction() const void TypingCommand::markMisspellingsAfterTyping() { - if (!document()->frame()->editor()->isContinuousSpellCheckingEnabled()) - return; // Take a look at the selection that results after typing and determine whether we need to spellcheck. // Since the word containing the current selection is never marked, this does a check to // see if typing made a new word that is not in the current selection. Basically, you diff --git a/WebCore/editing/VisiblePosition.cpp b/WebCore/editing/VisiblePosition.cpp index 7571035..3ca28f7 100644 --- a/WebCore/editing/VisiblePosition.cpp +++ b/WebCore/editing/VisiblePosition.cpp @@ -26,7 +26,6 @@ #include "config.h" #include "VisiblePosition.h" -#include "CString.h" #include "Document.h" #include "Element.h" #include "HTMLNames.h" @@ -36,7 +35,6 @@ #include "Text.h" #include "htmlediting.h" #include "visible_units.h" -#include <stdio.h> namespace WebCore { @@ -248,12 +246,12 @@ IntRect VisiblePosition::caretRect() const return m_deepPosition.node()->renderer()->caretRect(m_deepPosition.offset(), m_affinity); } -void VisiblePosition::debugPosition(const char* msg) const +void VisiblePosition::debugPosition(const char *msg) const { if (isNull()) fprintf(stderr, "Position [%s]: null\n", msg); else - fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, m_deepPosition.node()->nodeName().utf8().data(), m_deepPosition.node(), m_deepPosition.offset()); + fprintf(stderr, "Position [%s]: %s [%p] at %d\n", msg, m_deepPosition.node()->nodeName().deprecatedString().latin1(), m_deepPosition.node(), m_deepPosition.offset()); } #ifndef NDEBUG diff --git a/WebCore/editing/htmlediting.cpp b/WebCore/editing/htmlediting.cpp index c2d1fb5..a8d7702 100644 --- a/WebCore/editing/htmlediting.cpp +++ b/WebCore/editing/htmlediting.cpp @@ -367,11 +367,11 @@ int maxDeepOffset(const Node *node) String stringWithRebalancedWhitespace(const String& string, bool startIsStartOfParagraph, bool endIsEndOfParagraph) { - static String twoSpaces(" "); - static String nbsp("\xa0"); - static String pattern(" \xa0"); + static DeprecatedString twoSpaces(" "); + static DeprecatedString nbsp("\xa0"); + static DeprecatedString pattern(" \xa0"); - String rebalancedString = string; + DeprecatedString rebalancedString = string.deprecatedString(); rebalancedString.replace(noBreakSpace, ' '); rebalancedString.replace('\n', ' '); @@ -385,7 +385,7 @@ String stringWithRebalancedWhitespace(const String& string, bool startIsStartOfP if (endIsEndOfParagraph && rebalancedString[end] == ' ') rebalancedString.replace(end, 1, nbsp); - return rebalancedString; + return String(rebalancedString); } bool isTableStructureNode(const Node *node) diff --git a/WebCore/editing/markup.cpp b/WebCore/editing/markup.cpp index 4dad8ca..bcff364 100644 --- a/WebCore/editing/markup.cpp +++ b/WebCore/editing/markup.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved. + * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -36,6 +36,7 @@ #include "CSSValueKeywords.h" #include "Comment.h" #include "DeleteButtonController.h" +#include "DeprecatedStringList.h" #include "Document.h" #include "DocumentFragment.h" #include "DocumentType.h" @@ -44,6 +45,7 @@ #include "HTMLElement.h" #include "HTMLNames.h" #include "InlineTextBox.h" +#include "KURL.h" #include "Logging.h" #include "ProcessingInstruction.h" #include "QualifiedName.h" @@ -84,6 +86,11 @@ private: String m_value; }; +static inline void appendString(Vector<UChar>& result, const String& str) +{ + result.append(str.characters(), str.length()); +} + static void appendAttributeValue(Vector<UChar>& result, const String& attr) { const UChar* uchars = attr.characters(); @@ -99,60 +106,51 @@ static void appendAttributeValue(Vector<UChar>& result, const String& attr) switch (c) { case '&': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); - append(result, ampEntity); + appendString(result, ampEntity); lastCopiedFrom = i + 1; break; case '<': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); - append(result, ltEntity); + appendString(result, ltEntity); lastCopiedFrom = i + 1; break; case '"': result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); - append(result, quotEntity); + appendString(result, quotEntity); lastCopiedFrom = i + 1; } } result.append(uchars + lastCopiedFrom, len - lastCopiedFrom); } - -static void append(Vector<UChar>& vector, const char* string) -{ - const char* p = string; - while (*p) { - UChar c = *p++; - vector.append(c); - } -} -static String escapeContentText(const String& in) +static DeprecatedString escapeContentText(const String& in) { - Vector<UChar> s; + DeprecatedString s = ""; unsigned len = in.length(); unsigned lastCopiedFrom = 0; - s.reserveCapacity(len); - - const UChar* characters = in.characters(); + const UChar* uchars = in.characters(); + const DeprecatedChar* dchars = reinterpret_cast<const DeprecatedChar*>(uchars); for (unsigned i = 0; i < len; ++i) { - UChar c = characters[i]; + UChar c = uchars[i]; if ((c == '&') | (c == '<')) { - s.append(characters + lastCopiedFrom, i - lastCopiedFrom); + s.append(dchars + lastCopiedFrom, i - lastCopiedFrom); if (c == '&') - append(s, "&"); + s += "&"; else - append(s, "<"); + s += "<"; lastCopiedFrom = i + 1; } } - s.append(characters + lastCopiedFrom, len - lastCopiedFrom); + s.append(dchars + lastCopiedFrom, len - lastCopiedFrom); - return String::adopt(s); + return s; } + static void appendEscapedContent(Vector<UChar>& result, pair<const UChar*, size_t> range) { @@ -168,9 +166,9 @@ static void appendEscapedContent(Vector<UChar>& result, pair<const UChar*, size_ if ((c == '&') | (c == '<')) { result.append(uchars + lastCopiedFrom, i - lastCopiedFrom); if (c == '&') - append(result, ampEntity); + appendString(result, ampEntity); else - append(result, ltEntity); + appendString(result, ltEntity); lastCopiedFrom = i + 1; } } @@ -178,25 +176,33 @@ static void appendEscapedContent(Vector<UChar>& result, pair<const UChar*, size_ result.append(uchars + lastCopiedFrom, len - lastCopiedFrom); } -static void appendQuotedURLAttributeValue(Vector<UChar>& result, const String& urlString) +static inline void appendDeprecatedString(Vector<UChar>& result, const DeprecatedString& str) +{ + result.append(reinterpret_cast<const UChar*>(str.unicode()), str.length()); +} + +static void appendQuotedURLAttributeValue(Vector<UChar>& result, String urlString) { UChar quoteChar = '\"'; - String strippedURLString = urlString.stripWhiteSpace(); - if (protocolIs(strippedURLString, "javascript")) { +#ifdef ANDROID_JAVASCRIPT_SECURITY + if (protocolIs(urlString.stripWhiteSpace(), "javascript")) { +#else + if (urlString.stripWhiteSpace().startsWith("javascript:", false)) { +#endif // minimal escaping for javascript urls - if (strippedURLString.contains('"')) { - if (strippedURLString.contains('\'')) - strippedURLString.replace('\"', """); + if (urlString.contains('\"')) { + if (urlString.contains('\'')) + urlString.replace('\"', """); else quoteChar = '\''; } result.append(quoteChar); - append(result, strippedURLString); + appendString(result, urlString); result.append(quoteChar); return; } - // FIXME: This does not fully match other browsers. Firefox escapes spaces and other special characters. + // FIXME this does not fully match other browsers. Firefox escapes spaces and other special characters. result.append(quoteChar); appendAttributeValue(result, urlString); result.append(quoteChar); @@ -290,15 +296,6 @@ static void removeEnclosingMailBlockquoteStyle(CSSMutableStyleDeclaration* style blockquoteStyle->diff(style); } -static void removeDefaultStyles(CSSMutableStyleDeclaration* style, Document* document) -{ - if (!document || !document->documentElement()) - return; - - RefPtr<CSSMutableStyleDeclaration> documentStyle = computedStyle(document->documentElement())->copyInheritableProperties(); - documentStyle->diff(style); -} - static bool shouldAddNamespaceElem(const Element* elem) { // Don't add namespace attribute if it is already defined for this elem. @@ -338,10 +335,10 @@ static void appendNamespace(Vector<UChar>& result, const AtomicString& prefix, c namespaces.set(pre, ns.impl()); static const String xmlns("xmlns"); result.append(' '); - append(result, xmlns); + appendString(result, xmlns); if (!prefix.isEmpty()) { result.append(':'); - append(result, prefix); + appendString(result, prefix); } result.append('='); @@ -372,29 +369,36 @@ static void appendStartMarkup(Vector<UChar>& result, const Node *node, const Ran } bool useRenderedText = !enclosingNodeWithTag(Position(const_cast<Node*>(node), 0), selectTag); - String markup = escapeContentText(useRenderedText ? renderedText(node, range) : stringValueForRange(node, range)); + DeprecatedString markup = escapeContentText(useRenderedText ? renderedText(node, range) : stringValueForRange(node, range)); if (annotate) markup = convertHTMLTextToInterchangeFormat(markup, static_cast<const Text*>(node)); - append(result, markup); + appendDeprecatedString(result, markup); break; } case Node::COMMENT_NODE: - append(result, static_cast<const Comment*>(node)->toString()); + appendString(result, static_cast<const Comment*>(node)->toString()); + break; + case Node::DOCUMENT_NODE: { + // FIXME: I think the comment below (and therefore this code) is wrong now + // Documents do not normally contain a docType as a child node, force it to print here instead. + const DocumentType* docType = static_cast<const Document*>(node)->doctype(); + if (docType) + appendString(result, docType->toString()); break; - case Node::DOCUMENT_NODE: + } case Node::DOCUMENT_FRAGMENT_NODE: break; case Node::DOCUMENT_TYPE_NODE: - append(result, static_cast<const DocumentType*>(node)->toString()); + appendString(result, static_cast<const DocumentType*>(node)->toString()); break; case Node::PROCESSING_INSTRUCTION_NODE: - append(result, static_cast<const ProcessingInstruction*>(node)->toString()); + appendString(result, static_cast<const ProcessingInstruction*>(node)->toString()); break; case Node::ELEMENT_NODE: { result.append('<'); const Element* el = static_cast<const Element*>(node); bool convert = convertBlocksToInlines & isBlock(const_cast<Node*>(node)); - append(result, el->nodeNamePreservingCase()); + appendString(result, el->nodeNamePreservingCase()); NamedAttrMap *attrs = el->attributes(); unsigned length = attrs->length(); if (!documentIsHTML && namespaces && shouldAddNamespaceElem(el)) @@ -408,9 +412,9 @@ static void appendStartMarkup(Vector<UChar>& result, const Node *node, const Ran result.append(' '); if (documentIsHTML) - append(result, attr->name().localName()); + appendString(result, attr->name().localName()); else - append(result, attr->name().toString()); + appendString(result, attr->name().toString()); result.append('='); @@ -437,7 +441,7 @@ static void appendStartMarkup(Vector<UChar>& result, const Node *node, const Ran style->setProperty(CSS_PROP_DISPLAY, CSS_VAL_INLINE, true); if (style->length() > 0) { static const String stylePrefix(" style=\""); - append(result, stylePrefix); + appendString(result, stylePrefix); appendAttributeValue(result, style->cssText()); result.append('\"'); } @@ -452,7 +456,7 @@ static void appendStartMarkup(Vector<UChar>& result, const Node *node, const Ran break; } case Node::CDATA_SECTION_NODE: - append(result, static_cast<const CDATASection*>(node)->toString()); + appendString(result, static_cast<const CDATASection*>(node)->toString()); break; case Node::ATTRIBUTE_NODE: case Node::ENTITY_NODE: @@ -503,7 +507,7 @@ static void appendEndMarkup(Vector<UChar>& result, const Node* node) result.append('<'); result.append('/'); - append(result, static_cast<const Element*>(node)->nodeNamePreservingCase()); + appendString(result, static_cast<const Element*>(node)->nodeNamePreservingCase()); result.append('>'); } @@ -540,7 +544,7 @@ static void completeURLs(Node* node, const String& baseURL) { Vector<AttributeChange> changes; - KURL parsedBaseURL(baseURL); + KURL baseURLAsKURL(baseURL.deprecatedString()); Node* end = node->traverseNextSibling(); for (Node* n = node; n != end; n = n->traverseNextNode()) { @@ -550,8 +554,10 @@ static void completeURLs(Node* node, const String& baseURL) unsigned length = attrs->length(); for (unsigned i = 0; i < length; i++) { Attribute* attr = attrs->attributeItem(i); - if (e->isURLAttribute(attr)) - changes.append(AttributeChange(e, attr->name(), KURL(parsedBaseURL, attr->value()).string())); + if (e->isURLAttribute(attr)) { + String completedURL = KURL(baseURLAsKURL, attr->value().deprecatedString()).string(); + changes.append(AttributeChange(e, attr->name(), completedURL)); + } } } } @@ -620,10 +626,10 @@ String joinMarkups(const Vector<String> preMarkups, const Vector<String>& postMa result.reserveCapacity(length); for (size_t i = preCount; i > 0; --i) - append(result, preMarkups[i - 1]); + appendString(result, preMarkups[i - 1]); for (size_t i = 0; i < postCount; ++i) - append(result, postMarkups[i]); + appendString(result, postMarkups[i]); return String::adopt(result); } @@ -772,16 +778,6 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc specialCommonAncestor = commonAncestorBlock; } - bool selectedOneOrMoreParagraphs = startOfParagraph(visibleStart) != startOfParagraph(visibleEnd) || - isStartOfParagraph(visibleStart) && isEndOfParagraph(visibleEnd); - - // Retain the Mail quote level by including all ancestor mail block quotes. - if (lastClosed && annotate && selectedOneOrMoreParagraphs) { - for (Node *ancestor = lastClosed->parentNode(); ancestor; ancestor = ancestor->parentNode()) - if (isMailBlockquote(ancestor)) - specialCommonAncestor = ancestor; - } - Node* checkAncestor = specialCommonAncestor ? specialCommonAncestor : commonAncestor; if (checkAncestor->renderer()) { RefPtr<CSSMutableStyleDeclaration> checkAncestorStyle = computedStyle(checkAncestor)->copyInheritableProperties(); @@ -814,7 +810,7 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc if (style->length()) { Vector<UChar> openTag; static const String divStyle("<div style=\""); - append(openTag, divStyle); + appendString(openTag, divStyle); appendAttributeValue(openTag, style->cssText()); openTag.append('\"'); openTag.append('>'); @@ -837,9 +833,6 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc } } - static const String styleSpanOpen = String("<span class=\"" AppleStyleSpanClass "\" style=\""); - static const String styleSpanClose("</span>"); - // Add a wrapper span with the styles that all of the nodes in the markup inherit. Node* parentOfLastClosed = lastClosed ? lastClosed->parentNode() : 0; if (parentOfLastClosed && parentOfLastClosed->renderer()) { @@ -850,9 +843,6 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc // get the color of content pasted into blockquotes right. removeEnclosingMailBlockquoteStyle(style.get(), parentOfLastClosed); - // Document default styles will be added on another wrapper span. - removeDefaultStyles(style.get(), document); - // Since we are converting blocks to inlines, remove any inherited block properties that are in the style. // This cuts out meaningless properties and prevents properties from magically affecting blocks later // if the style is cloned for a new block element during a future editing operation. @@ -861,37 +851,35 @@ String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterc if (style->length() > 0) { Vector<UChar> openTag; - append(openTag, styleSpanOpen); + const String spanClassStyle = String("<span class=\"" AppleStyleSpanClass "\" style=\""); + appendString(openTag, spanClassStyle); appendAttributeValue(openTag, style->cssText()); openTag.append('\"'); openTag.append('>'); preMarkups.append(String::adopt(openTag)); - markups.append(styleSpanClose); - } - } - - if (lastClosed && lastClosed != document->documentElement()) { - // Add a style span with the document's default styles. We add these in a separate - // span so that at paste time we can differentiate between document defaults and user - // applied styles. - RefPtr<CSSMutableStyleDeclaration> defaultStyle = computedStyle(document->documentElement())->copyInheritableProperties(); - - if (defaultStyle->length() > 0) { - Vector<UChar> openTag; - append(openTag, styleSpanOpen); - appendAttributeValue(openTag, defaultStyle->cssText()); - openTag.append('\"'); - openTag.append('>'); - preMarkups.append(String::adopt(openTag)); - markups.append(styleSpanClose); + static const String spanCloseTag("</span>"); + markups.append(spanCloseTag); } } // FIXME: The interchange newline should be placed in the block that it's in, not after all of the content, unconditionally. if (annotate && needInterchangeNewlineAfter(visibleEnd.previous())) markups.append(interchangeNewlineString); - + + bool selectedOneOrMoreParagraphs = startOfParagraph(visibleStart) != startOfParagraph(visibleEnd) || + isStartOfParagraph(visibleStart) && isEndOfParagraph(visibleEnd); + + // Retain the Mail quote level by including all ancestor mail block quotes. + if (lastClosed && annotate && selectedOneOrMoreParagraphs) { + for (Node *ancestor = lastClosed->parentNode(); ancestor; ancestor = ancestor->parentNode()) { + if (isMailBlockquote(ancestor)) { + preMarkups.append(getStartMarkup(ancestor, updatedRange.get(), annotate)); + markups.append(getEndMarkup(ancestor)); + } + } + } + if (deleteButton) deleteButton->enable(); @@ -906,7 +894,7 @@ PassRefPtr<DocumentFragment> createFragmentFromMarkup(Document* document, const RefPtr<DocumentFragment> fragment = element->createContextualFragment(markup); - if (fragment && !baseURL.isEmpty() && baseURL != blankURL() && baseURL != document->baseURL()) + if (fragment && !baseURL.isEmpty() && baseURL != "about:blank" && baseURL != document->baseURL()) completeURLs(fragment.get(), baseURL); return fragment.release(); @@ -938,7 +926,7 @@ String createMarkup(const Node* node, EChildrenOnly includeChildren, Vector<Node return String::adopt(result); } -static void fillContainerFromString(ContainerNode* paragraph, const String& string) +static void fillContainerFromString(ContainerNode* paragraph, const DeprecatedString& string) { Document* document = paragraph->document(); @@ -951,13 +939,12 @@ static void fillContainerFromString(ContainerNode* paragraph, const String& stri ASSERT(string.find('\n') == -1); - Vector<String> tabList; - string.split('\t', true, tabList); - String tabText = ""; + DeprecatedStringList tabList = DeprecatedStringList::split('\t', string, true); + DeprecatedString tabText = ""; bool first = true; - size_t numEntries = tabList.size(); - for (size_t i = 0; i < numEntries; ++i) { - const String& s = tabList[i]; + while (!tabList.isEmpty()) { + DeprecatedString s = tabList.first(); + tabList.pop_front(); // append the non-tab textual part if (!s.isEmpty()) { @@ -966,15 +953,15 @@ static void fillContainerFromString(ContainerNode* paragraph, const String& stri ASSERT(ec == 0); tabText = ""; } - RefPtr<Node> textNode = document->createTextNode(stringWithRebalancedWhitespace(s, first, i + 1 == numEntries)); + RefPtr<Node> textNode = document->createTextNode(stringWithRebalancedWhitespace(s, first, tabList.isEmpty())); paragraph->appendChild(textNode.release(), ec); ASSERT(ec == 0); } // there is a tab after every entry, except the last entry // (if the last character is a tab, the list gets an extra empty entry) - if (i + 1 != numEntries) - tabText.append('\t'); + if (!tabList.isEmpty()) + tabText += '\t'; else if (!tabText.isEmpty()) { paragraph->appendChild(createTabSpanElement(document, tabText), ec); ASSERT(ec == 0); @@ -1002,7 +989,7 @@ PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String if (text.isEmpty()) return fragment.release(); - String string = text; + DeprecatedString string = text.deprecatedString(); string.replace("\r\n", "\n"); string.replace('\r', '\n'); @@ -1032,14 +1019,13 @@ PassRefPtr<DocumentFragment> createFragmentFromText(Range* context, const String Node* block = enclosingBlock(context->startNode()); bool useClonesOfEnclosingBlock = !block->hasTagName(bodyTag); - Vector<String> list; - string.split('\n', true, list); // true gets us empty strings in the list - size_t numLines = list.size(); - for (size_t i = 0; i < numLines; ++i) { - const String& s = list[i]; + DeprecatedStringList list = DeprecatedStringList::split('\n', string, true); // true gets us empty strings in the list + while (!list.isEmpty()) { + DeprecatedString s = list.first(); + list.pop_front(); RefPtr<Element> element; - if (s.isEmpty() && i + 1 == numLines) { + if (s.isEmpty() && list.isEmpty()) { // For last line, use the "magic BR" rather than a P. element = document->createElementNS(xhtmlNamespaceURI, "br", ec); ASSERT(ec == 0); |
