diff --git a/crates/egui/src/text_selection/text_cursor_state.rs b/crates/egui/src/text_selection/text_cursor_state.rs index 7aca96f8b19..ed51fde3153 100644 --- a/crates/egui/src/text_selection/text_cursor_state.rs +++ b/crates/egui/src/text_selection/text_cursor_state.rs @@ -302,18 +302,42 @@ pub fn find_line_start(text: &str, current_index: CCursor) -> CCursor { // number of multi byte chars. // We need to know the char index to be able to correctly set the cursor // later. - let chars_count = text.chars().count(); + let mut char_line_indexes: Vec = create_char_line_indexes(text); + let line_start_index = get_line_start_index(&mut char_line_indexes, current_index.index); - let position = text - .chars() - .rev() - .skip(chars_count - current_index.index) - .position(|x| x == '\n'); + CCursor::new(line_start_index) +} + +pub fn create_char_line_indexes(text: &str) -> Vec { + let mut line_indexes = vec![0]; - match position { - Some(pos) => CCursor::new(current_index.index - pos), - None => CCursor::new(0), + let mut count = 0; + for c in text.chars() { + count += 1; + if c == '\n' { + line_indexes.push(count); + } } + line_indexes.push(count); + + line_indexes +} + +pub fn get_line_start_index(line_indexes: &mut [usize], index: usize) -> usize { + let (_current_line, line_start) = get_line_and_start_index(line_indexes, index); + line_start +} + +pub fn get_line_and_start_index(line_indexes: &mut [usize], index: usize) -> (usize, usize) { + let mut current_line = 1; + for (i, line_start) in line_indexes.iter().enumerate() { + current_line = i; + if *line_start > index { + break; + } + } + + (current_line, line_indexes[current_line - 1]) } pub fn byte_index_from_char_index(s: &str, char_index: usize) -> usize { diff --git a/crates/egui/src/widgets/text_edit/text_buffer.rs b/crates/egui/src/widgets/text_edit/text_buffer.rs index f28878a1dd3..e70ce695af9 100644 --- a/crates/egui/src/widgets/text_edit/text_buffer.rs +++ b/crates/egui/src/widgets/text_edit/text_buffer.rs @@ -89,10 +89,12 @@ pub trait TextBuffer { fn decrease_indentation(&mut self, ccursor: &mut CCursor) { let line_start = find_line_start(self.as_str(), *ccursor); - let remove_len = if self.as_str()[line_start.index..].starts_with('\t') { + let remove_len = if self.as_str().chars().nth(line_start.index) == Some('\t') { Some(1) - } else if self.as_str()[line_start.index..] + } else if self + .as_str() .chars() + .skip(line_start.index) .take(TAB_SIZE) .all(|c| c == ' ') {