Example #1
0
bool isPlainTextMarkup(Node* node) {
  DCHECK(node);
  if (!isHTMLDivElement(*node))
    return false;

  HTMLDivElement& element = toHTMLDivElement(*node);
  if (!element.hasAttributes())
    return false;

  if (element.hasOneChild())
    return element.firstChild()->isTextNode() ||
           element.firstChild()->hasChildren();

  return element.hasChildCount(2) &&
         isTabHTMLSpanElementTextNode(element.firstChild()->firstChild()) &&
         element.lastChild()->isTextNode();
}
Example #2
0
Position InsertTextCommand::positionInsideTextNode(const Position& p)
{
    Position pos = p;
    if (isTabHTMLSpanElementTextNode(pos.anchorNode())) {
        RefPtrWillBeRawPtr<Text> textNode = document().createEditingTextNode("");
        insertNodeAtTabSpanPosition(textNode.get(), pos);
        return firstPositionInNode(textNode.get());
    }

    // Prepare for text input by looking at the specified position.
    // It may be necessary to insert a text node to receive characters.
    if (!pos.containerNode()->isTextNode()) {
        RefPtrWillBeRawPtr<Text> textNode = document().createEditingTextNode("");
        insertNodeAt(textNode.get(), pos);
        return firstPositionInNode(textNode.get());
    }

    return pos;
}
Example #3
0
Position InsertTextCommand::insertTab(const Position& pos)
{
    Position insertPos = VisiblePosition(pos, DOWNSTREAM).deepEquivalent();
    if (insertPos.isNull())
        return pos;

    Node* node = insertPos.containerNode();
    unsigned offset = node->isTextNode() ? insertPos.offsetInContainerNode() : 0;

    // keep tabs coalesced in tab span
    if (isTabHTMLSpanElementTextNode(node)) {
        RefPtrWillBeRawPtr<Text> textNode = toText(node);
        insertTextIntoNode(textNode, offset, "\t");
        return Position(textNode.release(), offset + 1);
    }

    // create new tab span
    RefPtrWillBeRawPtr<HTMLSpanElement> spanElement = createTabSpanElement(document());

    // place it
    if (!node->isTextNode()) {
        insertNodeAt(spanElement.get(), insertPos);
    } else {
        RefPtrWillBeRawPtr<Text> textNode = toText(node);
        if (offset >= textNode->length())
            insertNodeAfter(spanElement, textNode.release());
        else {
            // split node to make room for the span
            // NOTE: splitTextNode uses textNode for the
            // second node in the split, so we need to
            // insert the span before it.
            if (offset > 0)
                splitTextNode(textNode, offset);
            insertNodeBefore(spanElement, textNode.release());
        }
    }

    // return the position following the new tab
    return lastPositionInNode(spanElement.get());
}
Example #4
0
static HTMLElement* highestAncestorToWrapMarkup(
    const PositionTemplate<Strategy>& startPosition,
    const PositionTemplate<Strategy>& endPosition,
    EAnnotateForInterchange shouldAnnotate,
    Node* constrainingAncestor) {
  Node* firstNode = startPosition.nodeAsRangeFirstNode();
  // For compatibility reason, we use container node of start and end
  // positions rather than first node and last node in selection.
  Node* commonAncestor =
      Strategy::commonAncestor(*startPosition.computeContainerNode(),
                               *endPosition.computeContainerNode());
  DCHECK(commonAncestor);
  HTMLElement* specialCommonAncestor = nullptr;
  if (shouldAnnotate == AnnotateForInterchange) {
    // Include ancestors that aren't completely inside the range but are
    // required to retain the structure and appearance of the copied markup.
    specialCommonAncestor =
        ancestorToRetainStructureAndAppearance(commonAncestor);
    if (Node* parentListNode = enclosingNodeOfType(
            firstPositionInOrBeforeNode(firstNode), isListItem)) {
      EphemeralRangeTemplate<Strategy> markupRange =
          EphemeralRangeTemplate<Strategy>(startPosition, endPosition);
      EphemeralRangeTemplate<Strategy> nodeRange = normalizeRange(
          EphemeralRangeTemplate<Strategy>::rangeOfContents(*parentListNode));
      if (nodeRange == markupRange) {
        ContainerNode* ancestor = parentListNode->parentNode();
        while (ancestor && !isHTMLListElement(ancestor))
          ancestor = ancestor->parentNode();
        specialCommonAncestor = toHTMLElement(ancestor);
      }
    }

    // Retain the Mail quote level by including all ancestor mail block quotes.
    if (HTMLQuoteElement* highestMailBlockquote =
            toHTMLQuoteElement(highestEnclosingNodeOfType(
                firstPositionInOrBeforeNode(firstNode),
                isMailHTMLBlockquoteElement, CanCrossEditingBoundary)))
      specialCommonAncestor = highestMailBlockquote;
  }

  Node* checkAncestor =
      specialCommonAncestor ? specialCommonAncestor : commonAncestor;
  if (checkAncestor->layoutObject()) {
    HTMLElement* newSpecialCommonAncestor =
        toHTMLElement(highestEnclosingNodeOfType(
            Position::firstPositionInNode(checkAncestor),
            &isPresentationalHTMLElement, CanCrossEditingBoundary,
            constrainingAncestor));
    if (newSpecialCommonAncestor)
      specialCommonAncestor = newSpecialCommonAncestor;
  }

  // If a single tab is selected, commonAncestor will be a text node inside a
  // tab span. If two or more tabs are selected, commonAncestor will be the tab
  // span. In either case, if there is a specialCommonAncestor already, it will
  // necessarily be above any tab span that needs to be included.
  if (!specialCommonAncestor && isTabHTMLSpanElementTextNode(commonAncestor))
    specialCommonAncestor =
        toHTMLSpanElement(Strategy::parent(*commonAncestor));
  if (!specialCommonAncestor && isTabHTMLSpanElement(commonAncestor))
    specialCommonAncestor = toHTMLSpanElement(commonAncestor);

  if (HTMLAnchorElement* enclosingAnchor =
          toHTMLAnchorElement(enclosingElementWithTag(
              Position::firstPositionInNode(specialCommonAncestor
                                                ? specialCommonAncestor
                                                : commonAncestor),
              aTag)))
    specialCommonAncestor = enclosingAnchor;

  return specialCommonAncestor;
}