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()); }
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()); }
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; }