void DocumentMarkerController::removeMarkers(Range* range, DocumentMarker::MarkerTypes markerTypes, RemovePartiallyOverlappingMarkerOrNot shouldRemovePartiallyOverlappingMarker)
{
    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
        if (!possiblyHasMarkers(markerTypes))
            return;
        ASSERT(!m_markers.isEmpty());

        RefPtr<Range> textPiece = markedText.range();
        int startOffset = textPiece->startOffset();
        int endOffset = textPiece->endOffset();
        removeMarkers(textPiece->startContainer(), startOffset, endOffset - startOffset, markerTypes, shouldRemovePartiallyOverlappingMarker);
    }
}
Example #2
0
void InputElement::handleBeforeTextInsertedEvent(InputElementData& data, InputElement* inputElement, Element* element, Event* event)
{
    ASSERT(event->isBeforeTextInsertedEvent());
    // Make sure that the text to be inserted will not violate the maxLength.

    // We use RenderTextControlSingleLine::text() instead of InputElement::value()
    // because they can be mismatched by sanitizeValue() in
    // RenderTextControlSingleLine::subtreeHasChanged() in some cases.
    unsigned oldLength = numGraphemeClusters(toRenderTextControlSingleLine(element->renderer())->text());

    // selectionLength represents the selection length of this text field to be
    // removed by this insertion.
    // If the text field has no focus, we don't need to take account of the
    // selection length. The selection is the source of text drag-and-drop in
    // that case, and nothing in the text field will be removed.
    unsigned selectionLength = element->focused() ? numGraphemeClusters(plainText(element->document()->frame()->selection()->selection().toNormalizedRange().get())) : 0;
    ASSERT(oldLength >= selectionLength);

    // Selected characters will be removed by the next text event.
    unsigned baseLength = oldLength - selectionLength;
    unsigned maxLength = static_cast<unsigned>(inputElement->supportsMaxLength() ? data.maxLength() : s_maximumLength); // maxLength() can never be negative.
    unsigned appendableLength = maxLength > baseLength ? maxLength - baseLength : 0;

    // Truncate the inserted text to avoid violating the maxLength and other constraints.
    BeforeTextInsertedEvent* textEvent = static_cast<BeforeTextInsertedEvent*>(event);
#if ENABLE(WCSS)
    RefPtr<Range> range = element->document()->frame()->selection()->selection().toNormalizedRange();
    String candidateString = toRenderTextControlSingleLine(element->renderer())->text();
    if (selectionLength)
        candidateString.replace(range->startOffset(), range->endOffset(), textEvent->text());
    else
        candidateString.insert(textEvent->text(), range->startOffset());
    if (!isConformToInputMask(inputElement->data(), candidateString)) {
        textEvent->setText("");
        return;
      }
#endif
    textEvent->setText(sanitizeUserInputValue(inputElement, textEvent->text(), appendableLength));
}
void DocumentMarkerController::addDictationPhraseWithAlternativesMarker(Range* range, const Vector<String>& interpretations)
{
    ASSERT(interpretations.size() > 1);
    if (interpretations.size() <= 1)
        return;

    size_t numberOfAlternatives = interpretations.size() - 1;
    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
        RefPtr<Range> textPiece = markedText.range();
        DocumentMarker marker(DocumentMarker::DictationPhraseWithAlternatives, textPiece->startOffset(), textPiece->endOffset(), "", Vector<String>(numberOfAlternatives), RetainPtr<id>());
        for (size_t i = 0; i < numberOfAlternatives; ++i)
            marker.setAlternative(interpretations[i + 1], i);
        addMarker(&textPiece->startContainer(), marker);
    }
}
PassRefPtr<Range> CharacterIterator::range() const
{
    RefPtr<Range> r = m_textIterator.range();
    if (!m_textIterator.atEnd()) {
        if (m_textIterator.length() <= 1) {
            ASSERT(m_runOffset == 0);
        } else {
            int exception = 0;
            Node *n = r->startContainer(exception);
            ASSERT(n == r->endContainer(exception));
            int offset = r->startOffset(exception) + m_runOffset;
            r->setStart(n, offset, exception);
            r->setEnd(n, offset + 1, exception);
        }
    }
    return r.release();
}
void DOMSelection::deleteFromDocument()
{
    if (!m_frame)
        return;

    FrameSelection& selection = m_frame->selection();

    if (selection.isNone())
        return;

    RefPtr<Range> selectedRange = selection.selection().toNormalizedRange();
    if (!selectedRange)
        return;

    selectedRange->deleteContents(ASSERT_NO_EXCEPTION);

    setBaseAndExtent(&selectedRange->startContainer(), selectedRange->startOffset(), &selectedRange->startContainer(), selectedRange->startOffset());
}
void DocumentMarkerController::addTextMatchMarker(const Range* range, bool activeMatch)
{
    // Use a TextIterator to visit the potentially multiple nodes the range covers.
    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
        RefPtr<Range> textPiece = markedText.range();
        unsigned startOffset = textPiece->startOffset();
        unsigned endOffset = textPiece->endOffset();
        addMarker(textPiece->startContainer(), DocumentMarker(startOffset, endOffset, activeMatch));
        if (endOffset > startOffset) {
            // Rendered rects for markers in WebKit are not populated until each time
            // the markers are painted. However, we need it to happen sooner, because
            // the whole purpose of tickmarks on the scrollbar is to show where
            // matches off-screen are (that haven't been painted yet).
            Node* node = textPiece->startContainer();
            Vector<RenderedDocumentMarker*> markers = markersFor(node);
            markers[markers.size() - 1]->setRenderedRect(range->boundingBox());
        }
    }
}
Example #7
0
void DOMSelection::deleteFromDocument()
{
    if (!m_frame)
        return;

    FrameSelection* selection = m_frame->selection();

    if (selection->isNone())
        return;

    if (isCollapsed())
        selection->modify(FrameSelection::AlterationExtend, DirectionBackward, CharacterGranularity);

    RefPtr<Range> selectedRange = selection->selection().toNormalizedRange();
    if (!selectedRange)
        return;

    selectedRange->deleteContents(ASSERT_NO_EXCEPTION);

    setBaseAndExtent(selectedRange->startContainer(ASSERT_NO_EXCEPTION), selectedRange->startOffset(), selectedRange->startContainer(), selectedRange->startOffset(), ASSERT_NO_EXCEPTION);
}
void DOMSelection::deleteFromDocument()
{
    if (!m_frame)
        return;

    SelectionController* selection = m_frame->selection();

    if (selection->isNone())
        return;

    if (isCollapsed())
        selection->modify(SelectionController::EXTEND, SelectionController::BACKWARD, CharacterGranularity);

    RefPtr<Range> selectedRange = selection->selection().toNormalizedRange();

    ExceptionCode ec = 0;
    selectedRange->deleteContents(ec);
    ASSERT(!ec);

    setBaseAndExtent(selectedRange->startContainer(ec), selectedRange->startOffset(ec), selectedRange->startContainer(ec), selectedRange->startOffset(ec), ec);
    ASSERT(!ec);
}
void InputMethodController::setCompositionFromExistingText(const Vector<CompositionUnderline>& underlines, unsigned compositionStart, unsigned compositionEnd)
{
    Element* editable = m_frame.selection().rootEditableElement();
    Position base = m_frame.selection().base().downstream();
    Node* baseNode = base.anchorNode();
    if (editable->firstChild() == baseNode && editable->lastChild() == baseNode && baseNode->isTextNode()) {
        m_compositionNode = nullptr;
        m_customCompositionUnderlines.clear();

        if (base.anchorType() != Position::PositionIsOffsetInAnchor)
            return;
        if (!baseNode || baseNode != m_frame.selection().extent().anchorNode())
            return;

        m_compositionNode = toText(baseNode);
        RefPtr<Range> range = PlainTextRange(compositionStart, compositionEnd).createRange(*editable);
        m_compositionStart = range->startOffset();
        m_compositionEnd = range->endOffset();
        m_customCompositionUnderlines = underlines;
        size_t numUnderlines = m_customCompositionUnderlines.size();
        for (size_t i = 0; i < numUnderlines; ++i) {
            m_customCompositionUnderlines[i].startOffset += m_compositionStart;
            m_customCompositionUnderlines[i].endOffset += m_compositionStart;
        }

        // TODO(ojan): What was this for? Do we need it in sky since we
        // don't need to support legacy IMEs?
        if (baseNode->renderer())
            baseNode->document().scheduleVisualUpdate();

        return;
    }

    Editor::RevealSelectionScope revealSelectionScope(&editor());
    SelectionOffsetsScope selectionOffsetsScope(this);
    setSelectionOffsets(PlainTextRange(compositionStart, compositionEnd));
    setComposition(m_frame.selectedText(), underlines, 0, 0);
}
Example #10
0
bool DOMSelection::containsNode(Node& node, bool allowPartial) const
{
    if (!m_frame)
        return false;

    FrameSelection& selection = m_frame->selection();

    if (m_frame->document() != &node.document() || selection.isNone())
        return false;

    Ref<Node> protectedNode(node);
    RefPtr<Range> selectedRange = selection.selection().toNormalizedRange();

    ContainerNode* parentNode = node.parentNode();
    if (!parentNode || !parentNode->inDocument())
        return false;
    unsigned nodeIndex = node.computeNodeIndex();

    ExceptionCode ec = 0;
    bool nodeFullySelected = Range::compareBoundaryPoints(parentNode, nodeIndex, &selectedRange->startContainer(), selectedRange->startOffset(), ec) >= 0 && !ec
        && Range::compareBoundaryPoints(parentNode, nodeIndex + 1, &selectedRange->endContainer(), selectedRange->endOffset(), ec) <= 0 && !ec;
    ASSERT(!ec);
    if (nodeFullySelected)
        return true;

    bool nodeFullyUnselected = (Range::compareBoundaryPoints(parentNode, nodeIndex, &selectedRange->endContainer(), selectedRange->endOffset(), ec) > 0 && !ec)
        || (Range::compareBoundaryPoints(parentNode, nodeIndex + 1, &selectedRange->startContainer(), selectedRange->startOffset(), ec) < 0 && !ec);
    ASSERT(!ec);
    if (nodeFullyUnselected)
        return false;

    return allowPartial || node.isTextNode();
}
Example #11
0
bool DumpRenderTreeSupportEfl::selectedRange(Evas_Object* ewkView, int* start, int* length)
{
    if (!(start && length))
        return false;

    DRT_SUPPRT_PAGE_GET_OR_RETURN(ewkView, page, false);

    if (!page->focusController() || !page->focusController()->focusedOrMainFrame())
        return false;

    WebCore::Frame* frame = page->focusController()->focusedOrMainFrame();
    RefPtr<WebCore::Range> range = frame->selection()->toNormalizedRange().get();
    if (!range)
        return false;

    WebCore::Element* selectionRoot = frame->selection()->rootEditableElement();
    WebCore::Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();

    RefPtr<WebCore::Range> testRange = WebCore::Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
    *start = WebCore::TextIterator::rangeLength(testRange.get());

    WebCore::ExceptionCode ec;
    testRange->setEnd(range->endContainer(), range->endOffset(), ec);
    *length = WebCore::TextIterator::rangeLength(testRange.get());

    return true;
}
Example #12
0
bool DumpRenderTreeSupportGtk::selectedRange(WebKitWebView* webView, int* start, int* length)
{
    g_return_val_if_fail(WEBKIT_IS_WEB_VIEW(webView), false);
    g_return_val_if_fail(start && length, false);

    Frame* frame = core(webView)->focusController()->focusedOrMainFrame();
    if (!frame)
        return false;

    RefPtr<Range> range = frame->selection()->toNormalizedRange().get();
    if (!range)
        return false;

    Element* selectionRoot = frame->selection()->rootEditableElement();
    Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();

    RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
    ASSERT(testRange->startContainer() == scope);
    *start = TextIterator::rangeLength(testRange.get());

    ExceptionCode ec;
    testRange->setEnd(range->endContainer(), range->endOffset(), ec);
    ASSERT(testRange->startContainer() == scope);
    *length = TextIterator::rangeLength(testRange.get());

    return true;
}
void DocumentMarkerController::addDictationResultMarker(Range* range, const RetainPtr<id>& metadata)
{
    // Use a TextIterator to visit the potentially multiple nodes the range covers.
    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
        RefPtr<Range> textPiece = markedText.range();
        addMarker(textPiece->startContainer(), DocumentMarker(DocumentMarker::DictationResult, textPiece->startOffset(), textPiece->endOffset(), String(), Vector<String>(), metadata));
    }
}
void DocumentMarkerController::addDictationResultMarker(Range* range, const RetainPtr<id>& metadata)
{
    for (TextIterator markedText(range); !markedText.atEnd(); markedText.advance()) {
        RefPtr<Range> textPiece = markedText.range();
        addMarker(&textPiece->startContainer(), DocumentMarker(DocumentMarker::DictationResult, textPiece->startOffset(), textPiece->endOffset(), String(), Vector<String>(), metadata));
    }
}
bool DOMSelection::containsNode(const Node* n, bool allowPartial) const
{
    if (!m_frame)
        return false;

    SelectionController* selection = m_frame->selection();

    if (!n || selection->isNone())
        return false;

    Node* parentNode = n->parentNode();
    unsigned nodeIndex = n->nodeIndex();
    RefPtr<Range> selectedRange = selection->selection().toNormalizedRange();

    if (!parentNode)
        return false;

    ExceptionCode ec = 0;
    bool nodeFullySelected = Range::compareBoundaryPoints(parentNode, nodeIndex, selectedRange->startContainer(ec), selectedRange->startOffset(ec)) >= 0
        && Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange->endContainer(ec), selectedRange->endOffset(ec)) <= 0;
    ASSERT(!ec);
    if (nodeFullySelected)
        return true;

    bool nodeFullyUnselected = Range::compareBoundaryPoints(parentNode, nodeIndex, selectedRange->endContainer(ec), selectedRange->endOffset(ec)) > 0
        || Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange->startContainer(ec), selectedRange->startOffset(ec)) < 0;
    ASSERT(!ec);
    if (nodeFullyUnselected)
        return false;

    return allowPartial || n->isTextNode();
}
QVariantList DumpRenderTreeSupportQt::selectedRange(QWebPageAdapter *adapter)
{
    WebCore::Frame* frame = adapter->page->focusController()->focusedOrMainFrame();
    QVariantList selectedRange;
    RefPtr<Range> range = frame->selection()->toNormalizedRange().get();

    Element* selectionRoot = frame->selection()->rootEditableElement();
    Element* scope = selectionRoot ? selectionRoot : frame->document()->documentElement();

    RefPtr<Range> testRange = Range::create(scope->document(), scope, 0, range->startContainer(), range->startOffset());
    ASSERT(testRange->startContainer() == scope);
    int startPosition = TextIterator::rangeLength(testRange.get());

    ExceptionCode ec;
    testRange->setEnd(range->endContainer(), range->endOffset(), ec);
    ASSERT(testRange->startContainer() == scope);
    int endPosition = TextIterator::rangeLength(testRange.get());

    selectedRange << startPosition << (endPosition - startPosition);

    return selectedRange;

}
Example #17
0
bool DOMSelection::containsNode(const Node* n, bool allowPartial) const
{
    if (!m_frame)
        return false;

    FrameSelection& selection = m_frame->selection();

    if (!n || m_frame->document() != n->document() || selection.isNone())
        return false;

    unsigned nodeIndex = n->nodeIndex();
    RefPtr<Range> selectedRange = selection.selection().toNormalizedRange();

    ContainerNode* parentNode = n->parentNode();
    if (!parentNode)
        return false;

    TrackExceptionState exceptionState;
    bool nodeFullySelected = Range::compareBoundaryPoints(parentNode, nodeIndex, selectedRange->startContainer(), selectedRange->startOffset(), exceptionState) >= 0 && !exceptionState.hadException()
        && Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange->endContainer(), selectedRange->endOffset(), exceptionState) <= 0 && !exceptionState.hadException();
    if (exceptionState.hadException())
        return false;
    if (nodeFullySelected)
        return true;

    bool nodeFullyUnselected = (Range::compareBoundaryPoints(parentNode, nodeIndex, selectedRange->endContainer(), selectedRange->endOffset(), exceptionState) > 0 && !exceptionState.hadException())
        || (Range::compareBoundaryPoints(parentNode, nodeIndex + 1, selectedRange->startContainer(), selectedRange->startOffset(), exceptionState) < 0 && !exceptionState.hadException());
    ASSERT(!exceptionState.hadException());
    if (nodeFullyUnselected)
        return false;

    return allowPartial || n->isTextNode();
}