diff options
author | Matt Brubeck <mbrubeck@limpet.net> | 2016-04-27 11:22:02 -0700 |
---|---|---|
committer | Matt Brubeck <mbrubeck@limpet.net> | 2016-04-28 14:32:14 -0700 |
commit | 659305fe0a8f94e950ca64fab5ccef9949abd295 (patch) | |
tree | ac836803ac3fba799a4b4f73c24b4d0d2d208d6f /components/script/dom/htmlinputelement.rs | |
parent | dba878dfb278619bf2d808c0c21758a937ec6bb7 (diff) | |
download | servo-659305fe0a8f94e950ca64fab5ccef9949abd295.tar.gz servo-659305fe0a8f94e950ca64fab5ccef9949abd295.zip |
Use byte indices instead of char indices for text runs
Replace character indices with UTF-8 byte offsets throughout the code dealing
with text shaping and breaking. This eliminates a lot of complexity when
converting from one to the other, and interoperates better with the rest of
the Rust ecosystem.
Diffstat (limited to 'components/script/dom/htmlinputelement.rs')
-rw-r--r-- | components/script/dom/htmlinputelement.rs | 40 |
1 files changed, 22 insertions, 18 deletions
diff --git a/components/script/dom/htmlinputelement.rs b/components/script/dom/htmlinputelement.rs index ab753053b8f..a5bdacf44a4 100644 --- a/components/script/dom/htmlinputelement.rs +++ b/components/script/dom/htmlinputelement.rs @@ -43,10 +43,11 @@ use style::element_state::*; use textinput::KeyReaction::{DispatchInput, Nothing, RedrawSelection, TriggerDefaultAction}; use textinput::Lines::Single; use textinput::{TextInput, SelectionDirection}; -use util::str::{DOMString, search_index}; +use util::str::{DOMString}; const DEFAULT_SUBMIT_VALUE: &'static str = "Submit"; const DEFAULT_RESET_VALUE: &'static str = "Reset"; +const PASSWORD_REPLACEMENT_CHAR: char = '●'; #[derive(JSTraceable, PartialEq, Copy, Clone)] #[allow(dead_code)] @@ -174,7 +175,7 @@ pub trait LayoutHTMLInputElementHelpers { #[allow(unsafe_code)] unsafe fn size_for_layout(self) -> u32; #[allow(unsafe_code)] - unsafe fn selection_for_layout(self) -> Option<Range<isize>>; + unsafe fn selection_for_layout(self) -> Option<Range<usize>>; #[allow(unsafe_code)] unsafe fn checked_state_for_layout(self) -> bool; #[allow(unsafe_code)] @@ -207,8 +208,7 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { InputType::InputPassword => { let text = get_raw_textinput_value(self); if !text.is_empty() { - // The implementation of selection_for_layout expects a 1:1 mapping of chars. - text.chars().map(|_| '●').collect() + text.chars().map(|_| PASSWORD_REPLACEMENT_CHAR).collect() } else { String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone()) } @@ -216,7 +216,6 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { _ => { let text = get_raw_textinput_value(self); if !text.is_empty() { - // The implementation of selection_for_layout expects a 1:1 mapping of chars. String::from(text) } else { String::from((*self.unsafe_get()).placeholder.borrow_for_layout().clone()) @@ -233,24 +232,29 @@ impl LayoutHTMLInputElementHelpers for LayoutJS<HTMLInputElement> { #[allow(unrooted_must_root)] #[allow(unsafe_code)] - unsafe fn selection_for_layout(self) -> Option<Range<isize>> { + unsafe fn selection_for_layout(self) -> Option<Range<usize>> { if !(*self.unsafe_get()).upcast::<Element>().focus_state() { return None; } - // Use the raw textinput to get the index as long as we use a 1:1 char mapping - // in value_for_layout. - let raw = match (*self.unsafe_get()).input_type.get() { - InputType::InputText | - InputType::InputPassword => get_raw_textinput_value(self), - _ => return None - }; let textinput = (*self.unsafe_get()).textinput.borrow_for_layout(); - let selection = textinput.get_absolute_selection_range(); - let begin_byte = selection.begin(); - let begin = search_index(begin_byte, raw.char_indices()); - let length = search_index(selection.length(), raw[begin_byte..].char_indices()); - Some(Range::new(begin, length)) + + match (*self.unsafe_get()).input_type.get() { + InputType::InputPassword => { + let text = get_raw_textinput_value(self); + let sel = textinput.get_absolute_selection_range(); + + // Translate indices from the raw value to indices in the replacement value. + let char_start = text[.. sel.begin()].chars().count(); + let char_count = text[sel.begin() .. sel.end()].chars().count(); + + let bytes_per_char = PASSWORD_REPLACEMENT_CHAR.len_utf8(); + Some(Range::new(char_start * bytes_per_char, + char_count * bytes_per_char)) + } + InputType::InputText => Some(textinput.get_absolute_selection_range()), + _ => None + } } #[allow(unrooted_must_root)] |