diff options
-rw-r--r-- | dom/webidl/Selection.webidl | 6 | ||||
-rw-r--r-- | layout/generic/Selection.h | 4 | ||||
-rw-r--r-- | layout/generic/nsSelection.cpp | 49 |
3 files changed, 59 insertions, 0 deletions
diff --git a/dom/webidl/Selection.webidl b/dom/webidl/Selection.webidl index c3eac016cb..2b85b87f90 100644 --- a/dom/webidl/Selection.webidl +++ b/dom/webidl/Selection.webidl @@ -46,6 +46,12 @@ interface Selection { [Throws] boolean containsNode(Node node, boolean allowPartialContainment); + [Throws] + void setBaseAndExtent(Node anchorNode, + unsigned long anchorOffset, + Node focusNode, + unsigned long focusOffset); + stringifier; }; diff --git a/layout/generic/Selection.h b/layout/generic/Selection.h index 1e703b4669..83a2e2c688 100644 --- a/layout/generic/Selection.h +++ b/layout/generic/Selection.h @@ -207,6 +207,10 @@ public: void Modify(const nsAString& aAlter, const nsAString& aDirection, const nsAString& aGranularity, mozilla::ErrorResult& aRv); + void SetBaseAndExtent(nsINode& aAnchorNode, uint32_t aAnchorOffset, + nsINode& aFocusNode, uint32_t aFocusOffset, + mozilla::ErrorResult& aRv); + bool GetInterlinePosition(mozilla::ErrorResult& aRv); void SetInterlinePosition(bool aValue, mozilla::ErrorResult& aRv); diff --git a/layout/generic/nsSelection.cpp b/layout/generic/nsSelection.cpp index 3f8d11b486..301d799525 100644 --- a/layout/generic/nsSelection.cpp +++ b/layout/generic/nsSelection.cpp @@ -6434,6 +6434,55 @@ Selection::Modify(const nsAString& aAlter, const nsAString& aDirection, } } +void +Selection::SetBaseAndExtent(nsINode& aAnchorNode, uint32_t aAnchorOffset, + nsINode& aFocusNode, uint32_t aFocusOffset, + ErrorResult& aRv) +{ + if (!mFrameSelection) { + return; + } + + SelectionBatcher batch(this); + + int32_t relativePosition = + nsContentUtils::ComparePoints(&aAnchorNode, aAnchorOffset, + &aFocusNode, aFocusOffset); + nsINode* start = &aAnchorNode; + nsINode* end = &aFocusNode; + uint32_t startOffset = aAnchorOffset; + uint32_t endOffset = aFocusOffset; + if (relativePosition > 0) { + start = &aFocusNode; + end = &aAnchorNode; + startOffset = aFocusOffset; + endOffset = aAnchorOffset; + } + + RefPtr<nsRange> newRange; + nsresult rv = nsRange::CreateRange(start, startOffset, end, endOffset, + getter_AddRefs(newRange)); + // CreateRange returns IndexSizeError if any offset is out of bounds. + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return; + } + + rv = RemoveAllRanges(); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return; + } + + rv = AddRange(newRange); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return; + } + + SetDirection(relativePosition > 0 ? eDirPrevious : eDirNext); +} + /** SelectionLanguageChange modifies the cursor Bidi level after a change in keyboard direction * @param aLangRTL is true if the new language is right-to-left or false if the new language is left-to-right */ |