void InputMethodController::setCompositionFromExistingText(const Vector<CompositionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd)
{
    Element* editable = frame().selection().rootEditableElement();
    if (!editable)
        return;

    const EphemeralRange range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
    if (range.isNull())
        return;

    const Position start = range.startPosition();
    if (rootEditableElementOf(start) != editable)
        return;

    const Position end = range.endPosition();
    if (rootEditableElementOf(end) != editable)
        return;

    clear();

    for (const auto& underline : underlines) {
        unsigned underlineStart = compositionStart + underline.startOffset;
        unsigned underlineEnd = compositionStart + underline.endOffset;
        EphemeralRange ephemeralLineRange = PlainTextRange(underlineStart, underlineEnd).createRange(*editable);
        if (ephemeralLineRange.isNull())
            continue;
        frame().document()->markers().addCompositionMarker(ephemeralLineRange.startPosition(), ephemeralLineRange.endPosition(), underline.color, underline.thick, underline.backgroundColor);
    }

    m_hasComposition = true;
    if (!m_compositionRange)
        m_compositionRange = Range::create(range.document());
    m_compositionRange->setStart(range.startPosition());
    m_compositionRange->setEnd(range.endPosition());
}
Example #2
0
bool FrameCaret::shouldBlinkCaret() const {
  if (m_caretVisibility != CaretVisibility::Visible || !isActive())
    return false;

  Element* root = rootEditableElementOf(caretPosition().position());
  if (!root)
    return false;

  Element* focusedElement = root->document().focusedElement();
  if (!focusedElement)
    return false;

  return focusedElement->isShadowIncludingInclusiveAncestorOf(
      caretPosition().anchorNode());
}
Example #3
0
DocumentFragment* createFragmentFromText(const EphemeralRange& context,
                                         const String& text) {
  if (context.isNull())
    return nullptr;

  Document& document = context.document();
  DocumentFragment* fragment = document.createDocumentFragment();

  if (text.isEmpty())
    return fragment;

  String string = text;
  string.replace("\r\n", "\n");
  string.replace('\r', '\n');

  if (!isRichlyEditablePosition(context.startPosition()) ||
      shouldPreserveNewline(context)) {
    fragment->appendChild(document.createTextNode(string));
    if (string.endsWith('\n')) {
      HTMLBRElement* element = HTMLBRElement::create(document);
      element->setAttribute(classAttr, AppleInterchangeNewline);
      fragment->appendChild(element);
    }
    return fragment;
  }

  // A string with no newlines gets added inline, rather than being put into a
  // paragraph.
  if (string.find('\n') == kNotFound) {
    fillContainerFromString(fragment, string);
    return fragment;
  }

  // Break string into paragraphs. Extra line breaks turn into empty paragraphs.
  Element* block =
      enclosingBlock(context.startPosition().nodeAsRangeFirstNode());
  bool useClonesOfEnclosingBlock =
      block && !isHTMLBodyElement(*block) && !isHTMLHtmlElement(*block) &&
      block != rootEditableElementOf(context.startPosition());

  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];

    Element* element = nullptr;
    if (s.isEmpty() && i + 1 == numLines) {
      // For last line, use the "magic BR" rather than a P.
      element = HTMLBRElement::create(document);
      element->setAttribute(classAttr, AppleInterchangeNewline);
    } else {
      if (useClonesOfEnclosingBlock)
        element = block->cloneElementWithoutChildren();
      else
        element = createDefaultParagraphElement(document);
      fillContainerFromString(element, s);
    }
    fragment->appendChild(element);
  }
  return fragment;
}