From 0cf9adf6a5a21d7addcd4b1683ade19020f1e1f5 Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Thu, 9 Mar 2017 14:44:06 -0500 Subject: [PATCH] Bug 1343037 part 18. Implement nsTextEditorState::SetRangeText. r=ehsan MozReview-Commit-ID: FEo9yv5iu6U --- dom/html/HTMLInputElement.cpp | 102 ++++++------------------------- dom/html/HTMLInputElement.h | 7 ++- dom/html/HTMLTextAreaElement.cpp | 98 +++++------------------------ dom/html/HTMLTextAreaElement.h | 7 ++- dom/html/nsITextControlElement.h | 6 ++ dom/html/nsTextEditorState.cpp | 94 ++++++++++++++++++++++++++++ dom/html/nsTextEditorState.h | 11 ++++ 7 files changed, 151 insertions(+), 174 deletions(-) diff --git a/dom/html/HTMLInputElement.cpp b/dom/html/HTMLInputElement.cpp index 3b9c0d51eedc..67bf60b33fed 100644 --- a/dom/html/HTMLInputElement.cpp +++ b/dom/html/HTMLInputElement.cpp @@ -6291,102 +6291,36 @@ HTMLInputElement::SetRangeText(const nsAString& aReplacement, ErrorResult& aRv) return; } - int32_t start, end; - GetSelectionRange(&start, &end, aRv); - if (aRv.Failed()) { - return; - } - - SetRangeText(aReplacement, start, end, mozilla::dom::SelectionMode::Preserve, - aRv, start, end); + nsTextEditorState* state = GetEditorState(); + MOZ_ASSERT(state, "SupportsTextSelection() returned true!"); + state->SetRangeText(aReplacement, aRv); } void HTMLInputElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart, - uint32_t aEnd, const SelectionMode& aSelectMode, - ErrorResult& aRv, int32_t aSelectionStart, - int32_t aSelectionEnd) + uint32_t aEnd, SelectionMode aSelectMode, + ErrorResult& aRv) { if (!SupportsTextSelection()) { aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); return; } - if (aStart > aEnd) { - aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); - return; - } + nsTextEditorState* state = GetEditorState(); + MOZ_ASSERT(state, "SupportsTextSelection() returned true!"); + state->SetRangeText(aReplacement, aStart, aEnd, aSelectMode, aRv); +} - nsAutoString value; - GetNonFileValueInternal(value); - uint32_t inputValueLength = value.Length(); +void +HTMLInputElement::GetValueFromSetRangeText(nsAString& aValue) +{ + GetNonFileValueInternal(aValue); +} - if (aStart > inputValueLength) { - aStart = inputValueLength; - } - - if (aEnd > inputValueLength) { - aEnd = inputValueLength; - } - - if (aSelectionStart == -1 && aSelectionEnd == -1) { - GetSelectionRange(&aSelectionStart, &aSelectionEnd, aRv); - if (aRv.Failed()) { - return; - } - } - - if (aStart <= aEnd) { - value.Replace(aStart, aEnd - aStart, aReplacement); - nsresult rv = - SetValueInternal(value, nsTextEditorState::eSetValue_ByContent); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return; - } - } - - uint32_t newEnd = aStart + aReplacement.Length(); - int32_t delta = aReplacement.Length() - (aEnd - aStart); - - switch (aSelectMode) { - case mozilla::dom::SelectionMode::Select: - { - aSelectionStart = aStart; - aSelectionEnd = newEnd; - } - break; - case mozilla::dom::SelectionMode::Start: - { - aSelectionStart = aSelectionEnd = aStart; - } - break; - case mozilla::dom::SelectionMode::End: - { - aSelectionStart = aSelectionEnd = newEnd; - } - break; - case mozilla::dom::SelectionMode::Preserve: - { - if ((uint32_t)aSelectionStart > aEnd) { - aSelectionStart += delta; - } else if ((uint32_t)aSelectionStart > aStart) { - aSelectionStart = aStart; - } - - if ((uint32_t)aSelectionEnd > aEnd) { - aSelectionEnd += delta; - } else if ((uint32_t)aSelectionEnd > aStart) { - aSelectionEnd = newEnd; - } - } - break; - default: - MOZ_CRASH("Unknown mode!"); - } - - Optional direction; - SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv); +nsresult +HTMLInputElement::SetValueFromSetRangeText(const nsAString& aValue) +{ + return SetValueInternal(aValue, nsTextEditorState::eSetValue_ByContent); } Nullable diff --git a/dom/html/HTMLInputElement.h b/dom/html/HTMLInputElement.h index 41050a397da6..4111e3675b9a 100644 --- a/dom/html/HTMLInputElement.h +++ b/dom/html/HTMLInputElement.h @@ -239,6 +239,8 @@ public: NS_IMETHOD_(bool) GetPlaceholderVisibility() override; NS_IMETHOD_(void) InitializeKeyboardEventListeners() override; NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override; + virtual void GetValueFromSetRangeText(nsAString& aValue) override; + virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override; NS_IMETHOD_(bool) HasCachedSelection() override; // Methods for nsFormFillController so it can do selection operations on input @@ -730,9 +732,8 @@ public: void SetRangeText(const nsAString& aReplacement, ErrorResult& aRv); void SetRangeText(const nsAString& aReplacement, uint32_t aStart, - uint32_t aEnd, const SelectionMode& aSelectMode, - ErrorResult& aRv, int32_t aSelectionStart = -1, - int32_t aSelectionEnd = -1); + uint32_t aEnd, SelectionMode aSelectMode, + ErrorResult& aRv); bool Allowdirs() const { diff --git a/dom/html/HTMLTextAreaElement.cpp b/dom/html/HTMLTextAreaElement.cpp index 605da875e3e5..27bdf933e1bc 100644 --- a/dom/html/HTMLTextAreaElement.cpp +++ b/dom/html/HTMLTextAreaElement.cpp @@ -763,98 +763,28 @@ void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement, ErrorResult& aRv) { - int32_t start, end; - GetSelectionRange(&start, &end, aRv); - if (aRv.Failed()) { - return; - } - - SetRangeText(aReplacement, start, end, mozilla::dom::SelectionMode::Preserve, - aRv, start, end); + mState.SetRangeText(aReplacement, aRv); } void HTMLTextAreaElement::SetRangeText(const nsAString& aReplacement, uint32_t aStart, uint32_t aEnd, - const SelectionMode& aSelectMode, - ErrorResult& aRv, int32_t aSelectionStart, - int32_t aSelectionEnd) + SelectionMode aSelectMode, + ErrorResult& aRv) { - if (aStart > aEnd) { - aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); - return; - } + mState.SetRangeText(aReplacement, aStart, aEnd, aSelectMode, aRv); +} - nsAutoString value; - GetValueInternal(value, false); - uint32_t inputValueLength = value.Length(); +void +HTMLTextAreaElement::GetValueFromSetRangeText(nsAString& aValue) +{ + GetValueInternal(aValue, false); +} - if (aStart > inputValueLength) { - aStart = inputValueLength; - } - - if (aEnd > inputValueLength) { - aEnd = inputValueLength; - } - - if (aSelectionStart == -1 && aSelectionEnd == -1) { - GetSelectionRange(&aSelectionStart, &aSelectionEnd, aRv); - if (aRv.Failed()) { - return; - } - } - - if (aStart <= aEnd) { - value.Replace(aStart, aEnd - aStart, aReplacement); - nsresult rv = - SetValueInternal(value, nsTextEditorState::eSetValue_ByContent); - if (NS_FAILED(rv)) { - aRv.Throw(rv); - return; - } - } - - uint32_t newEnd = aStart + aReplacement.Length(); - int32_t delta = aReplacement.Length() - (aEnd - aStart); - - switch (aSelectMode) { - case mozilla::dom::SelectionMode::Select: - { - aSelectionStart = aStart; - aSelectionEnd = newEnd; - } - break; - case mozilla::dom::SelectionMode::Start: - { - aSelectionStart = aSelectionEnd = aStart; - } - break; - case mozilla::dom::SelectionMode::End: - { - aSelectionStart = aSelectionEnd = newEnd; - } - break; - case mozilla::dom::SelectionMode::Preserve: - { - if ((uint32_t)aSelectionStart > aEnd) { - aSelectionStart += delta; - } else if ((uint32_t)aSelectionStart > aStart) { - aSelectionStart = aStart; - } - - if ((uint32_t)aSelectionEnd > aEnd) { - aSelectionEnd += delta; - } else if ((uint32_t)aSelectionEnd > aStart) { - aSelectionEnd = newEnd; - } - } - break; - default: - MOZ_CRASH("Unknown mode!"); - } - - Optional direction; - SetSelectionRange(aSelectionStart, aSelectionEnd, direction, aRv); +nsresult +HTMLTextAreaElement::SetValueFromSetRangeText(const nsAString& aValue) +{ + return SetValueInternal(aValue, nsTextEditorState::eSetValue_ByContent); } nsresult diff --git a/dom/html/HTMLTextAreaElement.h b/dom/html/HTMLTextAreaElement.h index 115c345ca897..bca401052601 100644 --- a/dom/html/HTMLTextAreaElement.h +++ b/dom/html/HTMLTextAreaElement.h @@ -108,6 +108,8 @@ public: NS_IMETHOD_(bool) GetPlaceholderVisibility() override; NS_IMETHOD_(void) InitializeKeyboardEventListeners() override; NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) override; + virtual void GetValueFromSetRangeText(nsAString& aValue) override; + virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) override; NS_IMETHOD_(bool) HasCachedSelection() override; @@ -248,9 +250,8 @@ public: void SetRangeText(const nsAString& aReplacement, ErrorResult& aRv); void SetRangeText(const nsAString& aReplacement, uint32_t aStart, - uint32_t aEnd, const SelectionMode& aSelectMode, - ErrorResult& aRv, int32_t aSelectionStart = -1, - int32_t aSelectionEnd = -1); + uint32_t aEnd, SelectionMode aSelectMode, + ErrorResult& aRv); void SetRequired(bool aRequired, ErrorResult& aError) { diff --git a/dom/html/nsITextControlElement.h b/dom/html/nsITextControlElement.h index 72e53faecf9c..664fe8cb764a 100644 --- a/dom/html/nsITextControlElement.h +++ b/dom/html/nsITextControlElement.h @@ -174,6 +174,12 @@ public: */ NS_IMETHOD_(void) OnValueChanged(bool aNotify, bool aWasInteractiveUserChange) = 0; + /** + * Helpers for value manipulation from SetRangeText. + */ + virtual void GetValueFromSetRangeText(nsAString& aValue) = 0; + virtual nsresult SetValueFromSetRangeText(const nsAString& aValue) = 0; + static const int32_t DEFAULT_COLS = 20; static const int32_t DEFAULT_ROWS = 1; static const int32_t DEFAULT_ROWS_TEXTAREA = 2; diff --git a/dom/html/nsTextEditorState.cpp b/dom/html/nsTextEditorState.cpp index 0b839caaafca..7d198c201645 100644 --- a/dom/html/nsTextEditorState.cpp +++ b/dom/html/nsTextEditorState.cpp @@ -1843,6 +1843,100 @@ nsTextEditorState::SetSelectionRange(int32_t aSelectionStart, SetSelectionRange(aSelectionStart, aSelectionEnd, dir, aRv); } +void +nsTextEditorState::SetRangeText(const nsAString& aReplacement, + ErrorResult& aRv) +{ + int32_t start, end; + GetSelectionRange(&start, &end, aRv); + if (aRv.Failed()) { + return; + } + + SetRangeText(aReplacement, start, end, SelectionMode::Preserve, + aRv, start, end); +} + +void +nsTextEditorState::SetRangeText(const nsAString& aReplacement, uint32_t aStart, + uint32_t aEnd, SelectionMode aSelectMode, + ErrorResult& aRv, int32_t aSelectionStart, + int32_t aSelectionEnd) +{ + if (aStart > aEnd) { + aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); + return; + } + + nsAutoString value; + mTextCtrlElement->GetValueFromSetRangeText(value); + uint32_t inputValueLength = value.Length(); + + if (aStart > inputValueLength) { + aStart = inputValueLength; + } + + if (aEnd > inputValueLength) { + aEnd = inputValueLength; + } + + if (aSelectionStart == -1 && aSelectionEnd == -1) { + GetSelectionRange(&aSelectionStart, &aSelectionEnd, aRv); + if (aRv.Failed()) { + return; + } + } + + MOZ_ASSERT(aStart <= aEnd); + value.Replace(aStart, aEnd - aStart, aReplacement); + nsresult rv = mTextCtrlElement->SetValueFromSetRangeText(value); + if (NS_FAILED(rv)) { + aRv.Throw(rv); + return; + } + + uint32_t newEnd = aStart + aReplacement.Length(); + int32_t delta = aReplacement.Length() - (aEnd - aStart); + + switch (aSelectMode) { + case mozilla::dom::SelectionMode::Select: + { + aSelectionStart = aStart; + aSelectionEnd = newEnd; + } + break; + case mozilla::dom::SelectionMode::Start: + { + aSelectionStart = aSelectionEnd = aStart; + } + break; + case mozilla::dom::SelectionMode::End: + { + aSelectionStart = aSelectionEnd = newEnd; + } + break; + case mozilla::dom::SelectionMode::Preserve: + { + if ((uint32_t)aSelectionStart > aEnd) { + aSelectionStart += delta; + } else if ((uint32_t)aSelectionStart > aStart) { + aSelectionStart = aStart; + } + + if ((uint32_t)aSelectionEnd > aEnd) { + aSelectionEnd += delta; + } else if ((uint32_t)aSelectionEnd > aStart) { + aSelectionEnd = newEnd; + } + } + break; + default: + MOZ_CRASH("Unknown mode!"); + } + + SetSelectionRange(aSelectionStart, aSelectionEnd, Optional(), aRv); +} + HTMLInputElement* nsTextEditorState::GetParentNumberControl(nsFrame* aFrame) const { diff --git a/dom/html/nsTextEditorState.h b/dom/html/nsTextEditorState.h index 55708a9e9744..1733c4a9c5a7 100644 --- a/dom/html/nsTextEditorState.h +++ b/dom/html/nsTextEditorState.h @@ -15,6 +15,7 @@ #include "mozilla/Attributes.h" #include "mozilla/Maybe.h" #include "mozilla/WeakPtr.h" +#include "mozilla/dom/HTMLInputElementBinding.h" #include "mozilla/dom/Nullable.h" class nsTextInputListener; @@ -330,6 +331,16 @@ public: void SetSelectionDirection(const nsAString& aDirection, mozilla::ErrorResult& aRv); + // Set the range text. This basically implements + // https://html.spec.whatwg.org/multipage/forms.html#dom-textarea/input-setrangetext + void SetRangeText(const nsAString& aReplacement, mozilla::ErrorResult& aRv); + // The last two arguments are -1 if we don't know our selection range; + // otherwise they're the start and end of our selection range. + void SetRangeText(const nsAString& aReplacement, uint32_t aStart, + uint32_t aEnd, mozilla::dom::SelectionMode aSelectMode, + mozilla::ErrorResult& aRv, int32_t aSelectionStart = -1, + int32_t aSelectionEnd = -1); + void UpdateEditableState(bool aNotify) { if (mRootNode) { mRootNode->UpdateEditableState(aNotify);