-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix: panic when pressing Shift + TAB in a TextEdit #3878
Changes from 3 commits
b0b842f
3b8fe47
7812bbc
a493bf4
edc227a
a82763f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -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<usize> = 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<usize> { | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you use
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If CCursor is used instead of usize, By the way, the |
||||||
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 (_i, c) in text.chars().enumerate() { | ||||||
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 { | ||||||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What was wrong with the old code?
Maybe it just needs to handle the
char_count < current_index.index
case?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since UTF-8 characters use 1 to 4 bytes,
using
rev()
can cause a panic and terminate the program.You can test it by copying various UTF-8 characters
and using them in multiline().
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
.rev()
doesn't panic: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1647ea03b9ad85c69d72ee2189b73fc0There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mix the UTF8 characters with English, fill the screen
( with them using multiline(), egui_demo_app, web demo )
, and pressing Shift + TAB here and there and here and there.Please let me know if you can't find the panic occurrence.
Let me explain it to you again.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's sample TEXT.
pressing Shift + TAB here and there and here and there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are two more instances of
rev()
intext_cursor_state.rs
,fortunately, those two do not cause panics
but instead incorrectly select a block where UTF8 characters exist.
I will register this as a separate issue later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@emilk
Have you noticed the panic occurring?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't have time for this right now. I believe you that here is a panic in egui, but I don't think the panic is in the call to
.rev()
, and so I think a much simpler solution to your problem can be found.Run in debug mode and RUST_BACKTRACE=1 and paste the stack-trace to the actual panic.