diff --git a/reflection-app/src/textbuffer.rs b/reflection-app/src/textbuffer.rs index 8f23d070..31aad780 100644 --- a/reflection-app/src/textbuffer.rs +++ b/reflection-app/src/textbuffer.rs @@ -143,15 +143,15 @@ mod imp { #[upgrade_or] None, move |values| { - let pos: i32 = values.get(1).unwrap().get().unwrap(); + let offset: i32 = values.get(1).unwrap().get().unwrap(); let text: &str = values.get(2).unwrap().get().unwrap(); if buffer.inhibit_text_change() { return None; } - let mut pos_iter = buffer.iter_at_offset(pos); + let mut iter = buffer.iter_at_offset(offset); buffer.set_inhibit_text_change(true); - buffer.insert(&mut pos_iter, text); + buffer.insert(&mut iter, text); buffer.set_inhibit_text_change(false); None @@ -311,7 +311,7 @@ mod imp { if let Err(error) = result { error!("Failed to submit changes to the document: {error}"); } else { - info!("inserting new text {} at pos {}", new_text, offset); + info!("inserting new text {} at offset {}", new_text, offset); self.parent_insert_text(iter, new_text); } } diff --git a/reflection-doc/src/document.rs b/reflection-doc/src/document.rs index b0f776a4..b2df83d5 100644 --- a/reflection-doc/src/document.rs +++ b/reflection-doc/src/document.rs @@ -258,21 +258,21 @@ mod imp { } } - pub fn insert_text(&self, index: usize, chunk: &str) -> Result<()> { + pub fn insert_text(&self, offset: usize, chunk: &str) -> Result<()> { let doc = self.crdt_doc.get().expect("crdt_doc to be set"); let text = doc.get_text(&*TEXT_CONTAINER_ID); - text.insert(index, chunk)?; + text.insert(offset, chunk)?; doc.commit(); Ok(()) } - pub fn delete_text(&self, index: usize, len: usize) -> Result<()> { + pub fn delete_text(&self, offset: usize, len: usize) -> Result<()> { let doc = self.crdt_doc.get().expect("crdt_doc to be set"); let text = doc.get_text(&*TEXT_CONTAINER_ID); - text.delete(index, len)?; + text.delete(offset, len)?; doc.commit(); Ok(()) @@ -382,13 +382,13 @@ mod imp { self.subscription().is_some() } - fn emit_text_inserted(&self, pos: i32, text: String) { - if pos <= DOCUMENT_NAME_LENGTH as i32 { + fn emit_text_inserted(&self, offset: i32, text: String) { + if offset <= DOCUMENT_NAME_LENGTH as i32 { self.update_name(); } self.obj() - .emit_by_name::<()>("text-inserted", &[&pos, &text]); + .emit_by_name::<()>("text-inserted", &[&offset, &text]); } fn emit_range_deleted(&self, start: i32, end: i32) { @@ -468,21 +468,24 @@ mod imp { // Loro's text deltas are represented as QuillJS "Deltas" // See: https://quilljs.com/docs/delta/ for commit in text_deltas { - let mut index = 0; + // The `retain` and `delete` integers coming from Loro are the number of + // unicode codepoints (_not_ utf8 bytes or "characters"). In GTK this is + // called an "offset". + let mut offset = 0; for delta in commit { match delta { loro::TextDelta::Retain { retain, .. } => { - index += retain; + offset += retain; } loro::TextDelta::Insert { insert, .. } => { - let len = insert.len(); - obj.imp().emit_text_inserted(index as i32, insert); - index += len; + let chars_count = insert.chars().count(); + obj.imp().emit_text_inserted(offset as i32, insert); + offset += chars_count; } loro::TextDelta::Delete { delete } => { obj.imp().emit_range_deleted( - index as i32, - (index + delete) as i32, + offset as i32, + (offset + delete) as i32, ); } } @@ -739,8 +742,8 @@ impl Document { .build() } - pub fn insert_text(&self, pos: i32, text: &str) -> Result<()> { - self.imp().insert_text(pos as usize, text) + pub fn insert_text(&self, offset: i32, text: &str) -> Result<()> { + self.imp().insert_text(offset as usize, text) } pub fn delete_range(&self, start_pos: i32, end_pos: i32) -> Result<()> {