summaryrefslogtreecommitdiffstats
path: root/WebCore/editing/Editor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/editing/Editor.cpp')
-rw-r--r--WebCore/editing/Editor.cpp147
1 files changed, 76 insertions, 71 deletions
diff --git a/WebCore/editing/Editor.cpp b/WebCore/editing/Editor.cpp
index 2c303f9..b9dfc5d 100644
--- a/WebCore/editing/Editor.cpp
+++ b/WebCore/editing/Editor.cpp
@@ -340,9 +340,10 @@ bool Editor::tryDHTMLCopy()
if (m_frame->selection()->isInPasswordField())
return false;
- // Must be done before oncopy adds types and data to the pboard,
- // also done for security, as it erases data from the last copy/paste.
- Pasteboard::generalPasteboard()->clear();
+ if (canCopy())
+ // Must be done before oncopy adds types and data to the pboard,
+ // also done for security, as it erases data from the last copy/paste.
+ Pasteboard::generalPasteboard()->clear();
return !dispatchCPPEvent(eventNames().copyEvent, ClipboardWritable);
}
@@ -351,10 +352,11 @@ bool Editor::tryDHTMLCut()
{
if (m_frame->selection()->isInPasswordField())
return false;
-
- // Must be done before oncut adds types and data to the pboard,
- // also done for security, as it erases data from the last copy/paste.
- Pasteboard::generalPasteboard()->clear();
+
+ if (canCut())
+ // Must be done before oncut adds types and data to the pboard,
+ // also done for security, as it erases data from the last copy/paste.
+ Pasteboard::generalPasteboard()->clear();
return !dispatchCPPEvent(eventNames().cutEvent, ClipboardWritable);
}
@@ -653,9 +655,9 @@ PassRefPtr<Node> Editor::increaseSelectionListLevelOrdered()
if (!canEditRichly() || m_frame->selection()->isNone())
return 0;
- PassRefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(m_frame->document());
+ RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelOrdered(m_frame->document());
revealSelectionAfterEditingOperation();
- return newList;
+ return newList.release();
}
PassRefPtr<Node> Editor::increaseSelectionListLevelUnordered()
@@ -663,9 +665,9 @@ PassRefPtr<Node> Editor::increaseSelectionListLevelUnordered()
if (!canEditRichly() || m_frame->selection()->isNone())
return 0;
- PassRefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(m_frame->document());
+ RefPtr<Node> newList = IncreaseSelectionListLevelCommand::increaseSelectionListLevelUnordered(m_frame->document());
revealSelectionAfterEditingOperation();
- return newList;
+ return newList.release();
}
void Editor::decreaseSelectionListLevel()
@@ -769,66 +771,54 @@ bool Editor::clientIsEditable() const
return client() && client()->isEditable();
}
+// CSS properties that only has a visual difference when applied to text.
+static const int textOnlyProperties[] = {
+ CSSPropertyTextDecoration,
+ CSSPropertyWebkitTextDecorationsInEffect,
+ CSSPropertyFontStyle,
+ CSSPropertyFontWeight,
+ CSSPropertyColor,
+};
+
+static TriState triStateOfStyleInComputedStyle(CSSStyleDeclaration* desiredStyle, CSSComputedStyleDeclaration* computedStyle, bool ignoreTextOnlyProperties = false)
+{
+ RefPtr<CSSMutableStyleDeclaration> diff = getPropertiesNotInComputedStyle(desiredStyle, computedStyle);
+
+ if (ignoreTextOnlyProperties)
+ diff->removePropertiesInSet(textOnlyProperties, sizeof(textOnlyProperties)/sizeof(textOnlyProperties[0]));
+
+ if (!diff->length())
+ return TrueTriState;
+ else if (diff->length() == desiredStyle->length())
+ return FalseTriState;
+ return MixedTriState;
+}
+
bool Editor::selectionStartHasStyle(CSSStyleDeclaration* style) const
{
Node* nodeToRemove;
RefPtr<CSSComputedStyleDeclaration> selectionStyle = m_frame->selectionComputedStyle(nodeToRemove);
if (!selectionStyle)
return false;
-
- RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
-
- bool match = true;
- CSSMutableStyleDeclaration::const_iterator end = mutableStyle->end();
- for (CSSMutableStyleDeclaration::const_iterator it = mutableStyle->begin(); it != end; ++it) {
- int propertyID = (*it).id();
- if (!equalIgnoringCase(mutableStyle->getPropertyValue(propertyID), selectionStyle->getPropertyValue(propertyID))) {
- match = false;
- break;
- }
- }
-
+ TriState state = triStateOfStyleInComputedStyle(style, selectionStyle.get());
if (nodeToRemove) {
ExceptionCode ec = 0;
nodeToRemove->remove(ec);
ASSERT(ec == 0);
}
-
- return match;
-}
-
-static void updateState(CSSMutableStyleDeclaration* desiredStyle, CSSComputedStyleDeclaration* computedStyle, bool& atStart, TriState& state)
-{
- CSSMutableStyleDeclaration::const_iterator end = desiredStyle->end();
- for (CSSMutableStyleDeclaration::const_iterator it = desiredStyle->begin(); it != end; ++it) {
- int propertyID = (*it).id();
- String desiredProperty = desiredStyle->getPropertyValue(propertyID);
- String computedProperty = computedStyle->getPropertyValue(propertyID);
- TriState propertyState = equalIgnoringCase(desiredProperty, computedProperty)
- ? TrueTriState : FalseTriState;
- if (atStart) {
- state = propertyState;
- atStart = false;
- } else if (state != propertyState) {
- state = MixedTriState;
- break;
- }
- }
+ return state == TrueTriState;
}
TriState Editor::selectionHasStyle(CSSStyleDeclaration* style) const
{
- bool atStart = true;
TriState state = FalseTriState;
- RefPtr<CSSMutableStyleDeclaration> mutableStyle = style->makeMutable();
-
if (!m_frame->selection()->isRange()) {
Node* nodeToRemove;
RefPtr<CSSComputedStyleDeclaration> selectionStyle = m_frame->selectionComputedStyle(nodeToRemove);
if (!selectionStyle)
return FalseTriState;
- updateState(mutableStyle.get(), selectionStyle.get(), atStart, state);
+ state = triStateOfStyleInComputedStyle(style, selectionStyle.get());
if (nodeToRemove) {
ExceptionCode ec = 0;
nodeToRemove->remove(ec);
@@ -837,10 +827,15 @@ TriState Editor::selectionHasStyle(CSSStyleDeclaration* style) const
} else {
for (Node* node = m_frame->selection()->start().node(); node; node = node->traverseNextNode()) {
RefPtr<CSSComputedStyleDeclaration> nodeStyle = computedStyle(node);
- if (nodeStyle)
- updateState(mutableStyle.get(), nodeStyle.get(), atStart, state);
- if (state == MixedTriState)
- break;
+ if (nodeStyle) {
+ TriState nodeState = triStateOfStyleInComputedStyle(style, nodeStyle.get(), !node->isTextNode());
+ if (node == m_frame->selection()->start().node())
+ state = nodeState;
+ else if (state != nodeState) {
+ state = MixedTriState;
+ break;
+ }
+ }
if (node == m_frame->selection()->end().node())
break;
}
@@ -1064,9 +1059,9 @@ void Editor::paste()
void Editor::pasteAsPlainText()
{
- if (!canPaste())
+ if (!canPaste())
return;
- pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
+ pasteAsPlainTextWithPasteboard(Pasteboard::generalPasteboard());
}
void Editor::performDelete()
@@ -2204,7 +2199,7 @@ void Editor::markMisspellingsAfterTypingToPosition(const VisiblePosition &p)
if (!frame()->editor()->shouldInsertText(autocorrectedString, misspellingRange.get(), EditorInsertActionTyped))
return;
- frame()->editor()->replaceSelectionWithText(autocorrectedString, false, true);
+ frame()->editor()->replaceSelectionWithText(autocorrectedString, false, false);
// Reset the charet one character further.
frame()->selection()->moveTo(frame()->selection()->end());
@@ -2256,20 +2251,9 @@ static void markMisspellingsOrBadGrammar(Editor* editor, const VisibleSelection&
Node* editableNode = searchRange->startContainer();
if (!editableNode || !editableNode->isContentEditable())
return;
-
- // Ascend the DOM tree to find a "spellcheck" attribute.
- // When we find a "spellcheck" attribute, retrieve its value and exit if its value is "false".
- const Node* node = editor->frame()->document()->focusedNode();
- while (node) {
- if (node->isElementNode()) {
- const WebCore::AtomicString& value = static_cast<const Element*>(node)->getAttribute(spellcheckAttr);
- if (equalIgnoringCase(value, "true"))
- break;
- if (equalIgnoringCase(value, "false"))
- return;
- }
- node = node->parent();
- }
+
+ if (!editor->spellCheckingEnabledInFocusedNode())
+ return;
// Get the spell checker if it is available
if (!editor->client())
@@ -2287,6 +2271,24 @@ static void markMisspellingsOrBadGrammar(Editor* editor, const VisibleSelection&
}
}
+bool Editor::spellCheckingEnabledInFocusedNode() const
+{
+ // Ascend the DOM tree to find a "spellcheck" attribute.
+ // When we find a "spellcheck" attribute, retrieve its value and return false if its value is "false".
+ const Node* node = frame()->document()->focusedNode();
+ while (node) {
+ if (node->isElementNode()) {
+ const WebCore::AtomicString& value = static_cast<const Element*>(node)->getAttribute(spellcheckAttr);
+ if (equalIgnoringCase(value, "true"))
+ return true;
+ if (equalIgnoringCase(value, "false"))
+ return false;
+ }
+ node = node->parent();
+ }
+ return true;
+}
+
void Editor::markMisspellings(const VisibleSelection& selection, RefPtr<Range>& firstMisspellingRange)
{
markMisspellingsOrBadGrammar(this, selection, true, firstMisspellingRange);
@@ -2323,7 +2325,10 @@ void Editor::markAllMisspellingsAndBadGrammarInRanges(bool markSpelling, Range*
Node* editableNode = spellingRange->startContainer();
if (!editableNode || !editableNode->isContentEditable())
return;
-
+
+ if (!spellCheckingEnabledInFocusedNode())
+ return;
+
// Expand the range to encompass entire paragraphs, since text checking needs that much context.
int spellingRangeStartOffset = 0;
int spellingRangeEndOffset = 0;