void applyCommand(PassRefPtr<EditCommand> command) { DeleteButtonController *deleteButtonController = command->document()->frame()->editor()->deleteButtonController(); deleteButtonController->disable(); command->apply(); deleteButtonController->enable(); }
void EditCommand::apply() { ASSERT(m_document); ASSERT(m_document->frame()); Frame* frame = m_document->frame(); if (isTopLevelCommand()) { if (!endingSelection().isContentRichlyEditable()) { switch (editingAction()) { case EditActionTyping: case EditActionPaste: case EditActionDrag: case EditActionSetWritingDirection: case EditActionCut: case EditActionUnspecified: break; default: ASSERT_NOT_REACHED(); return; } } } // Changes to the document may have been made since the last editing operation that // require a layout, as in <rdar://problem/5658603>. Low level operations, like // RemoveNodeCommand, don't require a layout because the high level operations that // use them perform one if one is necessary (like for the creation of VisiblePositions). if (isTopLevelCommand()) updateLayout(); { EventQueueScope scope; DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController(); deleteButtonController->disable(); doApply(); deleteButtonController->enable(); } if (isTopLevelCommand()) { // Only need to call appliedEditing for top-level commands, and TypingCommands do it on their // own (see TypingCommand::typingAddedToOpenCommand). if (!isTypingCommand()) frame->editor()->appliedEditing(this); } setShouldRetainAutocorrectionIndicator(false); }
void EditCommand::apply() { ASSERT(m_document); ASSERT(m_document->frame()); Frame* frame = m_document->frame(); if (!m_parent) { if (!endingSelection().isContentRichlyEditable()) { switch (editingAction()) { case EditActionTyping: case EditActionPaste: case EditActionDrag: case EditActionSetWritingDirection: case EditActionCut: case EditActionUnspecified: break; default: ASSERT_NOT_REACHED(); return; } } } // Changes to the document may have been made since the last editing operation that // require a layout, as in <rdar://problem/5658603>. Low level operations, like // RemoveNodeCommand, don't require a layout because the high level operations that // use them perform one if one is necessary (like for the creation of VisiblePositions). if (!m_parent) updateLayout(); // All high level commands, and all commands that a TypingCommand spawns, except for // text insertions, which should restore a removed anchor, should clear it. if (!m_parent && !isTypingCommand()) frame->editor()->setRemovedAnchor(0); if (m_parent && m_parent->isTypingCommand() && !isInsertTextCommand()) frame->editor()->setRemovedAnchor(0); DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController(); deleteButtonController->disable(); doApply(); deleteButtonController->enable(); if (!m_parent) { updateLayout(); frame->editor()->appliedEditing(this); } }
void EditCommand::reapply() { ASSERT(m_document); ASSERT(m_document->frame()); Frame* frame = m_document->frame(); DeleteButtonController *deleteButtonController = frame->editor()->deleteButtonController(); deleteButtonController->disable(); doReapply(); deleteButtonController->enable(); if (!m_parent) { updateLayout(); frame->editor()->reappliedEditing(this); } }
EditCommand::EditCommand(Document* document) : m_document(document) , m_parent(0) { ASSERT(m_document); ASSERT(m_document->frame()); DeleteButtonController* deleteButton = m_document->frame()->editor()->deleteButtonController(); setStartingSelection(avoidIntersectionWithNode(m_document->frame()->selection()->selection(), deleteButton ? deleteButton->containerElement() : 0)); setEndingSelection(m_startingSelection); }
void EditCommand::apply() { ASSERT(m_document); ASSERT(m_document->frame()); Frame* frame = m_document->frame(); if (!m_parent) { if (!endingSelection().isContentRichlyEditable()) { switch (editingAction()) { case EditActionTyping: case EditActionPaste: case EditActionDrag: case EditActionSetWritingDirection: case EditActionCut: case EditActionUnspecified: break; default: ASSERT_NOT_REACHED(); return; } } } DeleteButtonController *deleteButtonController = frame->editor()->deleteButtonController(); deleteButtonController->disable(); doApply(); deleteButtonController->enable(); // FIXME: Improve typing style. // See this bug: <rdar://problem/3769899> Implementation of typing style needs improvement if (!preservesTypingStyle()) { setTypingStyle(0); if (!m_parent) frame->editor()->setRemovedAnchor(0); } if (!m_parent) { updateLayout(); frame->editor()->appliedEditing(this); } }
void EditCommand::reapply() { ASSERT(m_document); ASSERT(m_document->frame()); Frame* frame = m_document->frame(); // Changes to the document may have been made since the last editing operation that // require a layout, as in <rdar://problem/5658603>. Low level operations, like // RemoveNodeCommand, don't require a layout because the high level operations that // use them perform one if one is necessary (like for the creation of VisiblePositions). if (isTopLevelCommand()) updateLayout(); DeleteButtonController* deleteButtonController = frame->editor()->deleteButtonController(); deleteButtonController->disable(); doReapply(); deleteButtonController->enable(); if (isTopLevelCommand()) frame->editor()->reappliedEditing(this); }
// FIXME: Shouldn't we omit style info when annotate == DoNotAnnotateForInterchange? // FIXME: At least, annotation and style info should probably not be included in range.markupString() String createMarkup(const Range* range, Vector<Node*>* nodes, EAnnotateForInterchange shouldAnnotate, bool convertBlocksToInlines, EAbsoluteURLs shouldResolveURLs) { DEFINE_STATIC_LOCAL(const String, interchangeNewlineString, (ASCIILiteral("<br class=\"" AppleInterchangeNewline "\">"))); if (!range) return ""; Document* document = range->ownerDocument(); if (!document) return ""; // Disable the delete button so it's elements are not serialized into the markup, // but make sure neither endpoint is inside the delete user interface. Frame* frame = document->frame(); DeleteButtonController* deleteButton = frame ? frame->editor()->deleteButtonController() : 0; RefPtr<Range> updatedRange = avoidIntersectionWithNode(range, deleteButton ? deleteButton->containerElement() : 0); if (!updatedRange) return ""; if (deleteButton) deleteButton->disable(); bool collapsed = updatedRange->collapsed(ASSERT_NO_EXCEPTION); if (collapsed) return ""; Node* commonAncestor = updatedRange->commonAncestorContainer(ASSERT_NO_EXCEPTION); if (!commonAncestor) return ""; document->updateLayoutIgnorePendingStylesheets(); Node* body = enclosingNodeWithTag(firstPositionInNode(commonAncestor), bodyTag); Node* fullySelectedRoot = 0; // FIXME: Do this for all fully selected blocks, not just the body. if (body && areRangesEqual(VisibleSelection::selectionFromContentsOfNode(body).toNormalizedRange().get(), range)) fullySelectedRoot = body; Node* specialCommonAncestor = highestAncestorToWrapMarkup(updatedRange.get(), shouldAnnotate); StyledMarkupAccumulator accumulator(nodes, shouldResolveURLs, shouldAnnotate, updatedRange.get(), specialCommonAncestor); Node* pastEnd = updatedRange->pastLastNode(); Node* startNode = updatedRange->firstNode(); VisiblePosition visibleStart(updatedRange->startPosition(), VP_DEFAULT_AFFINITY); VisiblePosition visibleEnd(updatedRange->endPosition(), VP_DEFAULT_AFFINITY); if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(visibleStart)) { if (visibleStart == visibleEnd.previous()) { if (deleteButton) deleteButton->enable(); return interchangeNewlineString; } accumulator.appendString(interchangeNewlineString); startNode = visibleStart.next().deepEquivalent().deprecatedNode(); if (pastEnd && Range::compareBoundaryPoints(startNode, 0, pastEnd, 0, ASSERT_NO_EXCEPTION) >= 0) { if (deleteButton) deleteButton->enable(); return interchangeNewlineString; } } Node* lastClosed = accumulator.serializeNodes(startNode, pastEnd); if (specialCommonAncestor && lastClosed) { // Also include all of the ancestors of lastClosed up to this special ancestor. for (ContainerNode* ancestor = lastClosed->parentNode(); ancestor; ancestor = ancestor->parentNode()) { if (ancestor == fullySelectedRoot && !convertBlocksToInlines) { RefPtr<EditingStyle> fullySelectedRootStyle = styleFromMatchedRulesAndInlineDecl(fullySelectedRoot); // Bring the background attribute over, but not as an attribute because a background attribute on a div // appears to have no effect. if ((!fullySelectedRootStyle || !fullySelectedRootStyle->style() || !fullySelectedRootStyle->style()->getPropertyCSSValue(CSSPropertyBackgroundImage)) && static_cast<Element*>(fullySelectedRoot)->hasAttribute(backgroundAttr)) fullySelectedRootStyle->style()->setProperty(CSSPropertyBackgroundImage, "url('" + static_cast<Element*>(fullySelectedRoot)->getAttribute(backgroundAttr) + "')"); if (fullySelectedRootStyle->style()) { // Reset the CSS properties to avoid an assertion error in addStyleMarkup(). // This assertion is caused at least when we select all text of a <body> element whose // 'text-decoration' property is "inherit", and copy it. if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(), CSSPropertyTextDecoration)) fullySelectedRootStyle->style()->setProperty(CSSPropertyTextDecoration, CSSValueNone); if (!propertyMissingOrEqualToNone(fullySelectedRootStyle->style(), CSSPropertyWebkitTextDecorationsInEffect)) fullySelectedRootStyle->style()->setProperty(CSSPropertyWebkitTextDecorationsInEffect, CSSValueNone); accumulator.wrapWithStyleNode(fullySelectedRootStyle->style(), document, true); } } else { // Since this node and all the other ancestors are not in the selection we want to set RangeFullySelectsNode to DoesNotFullySelectNode // so that styles that affect the exterior of the node are not included. accumulator.wrapWithNode(ancestor, convertBlocksToInlines, StyledMarkupAccumulator::DoesNotFullySelectNode); } if (nodes) nodes->append(ancestor); lastClosed = ancestor; if (ancestor == specialCommonAncestor) break; } } // FIXME: The interchange newline should be placed in the block that it's in, not after all of the content, unconditionally. if (shouldAnnotate == AnnotateForInterchange && needInterchangeNewlineAfter(visibleEnd.previous())) accumulator.appendString(interchangeNewlineString); if (deleteButton) deleteButton->enable(); return accumulator.takeResults(); }