static void writeSelection(TextStream& ts, const RenderObject* o) { Node* n = o->node(); if (!n || !n->isDocumentNode()) return; Document* doc = static_cast<Document*>(n); Frame* frame = doc->frame(); if (!frame) return; VisibleSelection selection = frame->selection()->selection(); if (selection.isCaret()) { ts << "caret: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().node()); if (selection.affinity() == UPSTREAM) ts << " (upstream affinity)"; ts << "\n"; } else if (selection.isRange()) ts << "selection start: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().node()) << "\n" << "selection end: position " << selection.end().deprecatedEditingOffset() << " of " << nodePosition(selection.end().node()) << "\n"; }
static void getSelectionOffsetsForObject(AccessibilityObject* coreObject, VisibleSelection& selection, gint& startOffset, gint& endOffset) { // Default values, unless the contrary is proved. startOffset = 0; endOffset = 0; Node* node = getNodeForAccessibilityObject(coreObject); if (!node) return; if (selection.isNone()) return; // We need to limit our search to positions that fall inside the domain of the current object. Position firstValidPosition = firstPositionInOrBeforeNode(node->firstDescendant()); Position lastValidPosition = lastPositionInOrAfterNode(node->lastDescendant()); // Early return with proper values if the selection falls entirely out of the object. if (!selectionBelongsToObject(coreObject, selection)) { startOffset = comparePositions(selection.start(), firstValidPosition) < 0 ? 0 : accessibilityObjectLength(coreObject); endOffset = startOffset; return; } // Find the proper range for the selection that falls inside the object. Position nodeRangeStart = selection.start(); if (comparePositions(nodeRangeStart, firstValidPosition) < 0) nodeRangeStart = firstValidPosition; Position nodeRangeEnd = selection.end(); if (comparePositions(nodeRangeEnd, lastValidPosition) > 0) nodeRangeEnd = lastValidPosition; // Calculate position of the selected range inside the object. Position parentFirstPosition = firstPositionInOrBeforeNode(node); RefPtr<Range> rangeInParent = Range::create(&node->document(), parentFirstPosition, nodeRangeStart); // Set values for start offsets and calculate initial range length. // These values might be adjusted later to cover special cases. startOffset = webCoreOffsetToAtkOffset(coreObject, TextIterator::rangeLength(rangeInParent.get(), true)); RefPtr<Range> nodeRange = Range::create(&node->document(), nodeRangeStart, nodeRangeEnd); int rangeLength = TextIterator::rangeLength(nodeRange.get(), true); // Special cases that are only relevant when working with *_END boundaries. if (selection.affinity() == UPSTREAM) { VisiblePosition visibleStart(nodeRangeStart, UPSTREAM); VisiblePosition visibleEnd(nodeRangeEnd, UPSTREAM); // We need to adjust offsets when finding wrapped lines so the position at the end // of the line is properly taking into account when calculating the offsets. if (isEndOfLine(visibleStart) && !lineBreakExistsAtVisiblePosition(visibleStart)) { if (isStartOfLine(visibleStart.next())) rangeLength++; if (!isEndOfBlock(visibleStart)) startOffset = std::max(startOffset - 1, 0); } if (isEndOfLine(visibleEnd) && !lineBreakExistsAtVisiblePosition(visibleEnd) && !isEndOfBlock(visibleEnd)) rangeLength--; } endOffset = std::min(startOffset + rangeLength, static_cast<int>(accessibilityObjectLength(coreObject))); }