Correct unicode handling for text input

This commit is contained in:
Charles Vandevoorde 2017-03-05 10:21:47 +01:00 committed by charlesvdv
parent 78210c3c94
commit 26e6c09776
5 changed files with 17 additions and 7 deletions

1
Cargo.lock generated
View file

@ -2296,6 +2296,7 @@ dependencies = [
"style_traits 0.0.1",
"time 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)",
"tinyfiledialogs 2.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
"unicode-segmentation 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"url 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"uuid 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"webrender_traits 0.23.1 (git+https://github.com/servo/webrender)",

View file

@ -85,6 +85,7 @@ smallvec = "0.1"
style = {path = "../style"}
style_traits = {path = "../style_traits"}
time = "0.1.12"
unicode-segmentation = "1.1.0"
url = {version = "1.2", features = ["heap_size", "query_encoding"]}
uuid = {version = "0.4", features = ["v4"]}
xml5ever = {version = "0.4", features = ["unstable"]}

View file

@ -1112,7 +1112,7 @@ impl VirtualMethods for HTMLInputElement {
translated_y
);
if let Some(i) = index {
self.textinput.borrow_mut().edit_point.index = i as usize;
self.textinput.borrow_mut().set_edit_point_index(i as usize);
// trigger redraw
self.upcast::<Node>().dirty(NodeDamage::OtherNodeDamage);
event.PreventDefault();

View file

@ -95,6 +95,7 @@ extern crate style_traits;
extern crate time;
#[cfg(any(target_os = "macos", target_os = "linux", target_os = "windows"))]
extern crate tinyfiledialogs;
extern crate unicode_segmentation;
extern crate url;
extern crate uuid;
extern crate webrender_traits;

View file

@ -14,6 +14,7 @@ use std::cmp::{max, min};
use std::default::Default;
use std::ops::Range;
use std::usize;
use unicode_segmentation::UnicodeSegmentation;
#[derive(Copy, Clone, PartialEq)]
pub enum Selection {
@ -376,18 +377,16 @@ impl<T: ClipboardProvider> TextInput<T> {
}
let adjust = {
let current_line = &self.lines[self.edit_point.line];
// FIXME: We adjust by one code point, but it proably should be one grapheme cluster
// https://github.com/unicode-rs/unicode-segmentation
match direction {
Direction::Forward => {
match current_line[self.edit_point.index..].chars().next() {
Some(c) => c.len_utf8() as isize,
match current_line[self.edit_point.index..].graphemes(true).next() {
Some(c) => c.len() as isize,
None => 1, // Going to the next line is a "one byte" offset
}
}
Direction::Backward => {
match current_line[..self.edit_point.index].chars().next_back() {
Some(c) => -(c.len_utf8() as isize),
match current_line[..self.edit_point.index].graphemes(true).next_back() {
Some(c) => -(c.len() as isize),
None => -1, // Going to the previous line is a "one byte" offset
}
}
@ -677,4 +676,12 @@ impl<T: ClipboardProvider> TextInput<T> {
selection_start as u32
}
pub fn set_edit_point_index(&mut self, index: usize) {
let byte_size = self.lines[self.edit_point.line]
.graphemes(true)
.take(index)
.fold(0, |acc, x| acc + x.len());
self.edit_point.index = byte_size;
}
}