@@ -39,15 +39,15 @@ pub use items::MAX_TAB_TITLE_LEN;
pub use language::{char_kind, CharKind};
use language::{
BracketPair, Buffer, CodeAction, CodeLabel, Completion, Diagnostic, DiagnosticSeverity,
- IndentKind, IndentSize, Language, OffsetRangeExt, Point, Selection, SelectionGoal,
+ IndentKind, IndentSize, Language, OffsetRangeExt, OffsetUtf16, Point, Selection, SelectionGoal,
TransactionId,
};
use link_go_to_definition::LinkGoToDefinitionState;
-use multi_buffer::MultiBufferChunks;
pub use multi_buffer::{
Anchor, AnchorRangeExt, ExcerptId, ExcerptRange, MultiBuffer, MultiBufferSnapshot, ToOffset,
ToPoint,
};
+use multi_buffer::{MultiBufferChunks, ToOffsetUtf16};
use ordered_float::OrderedFloat;
use project::{LocationLink, Project, ProjectPath, ProjectTransaction};
use selections_collection::{resolve_multiple, MutableSelectionsCollection, SelectionsCollection};
@@ -5877,27 +5877,33 @@ impl View for Editor {
context
}
- fn text_for_range(&self, range: Range<usize>, cx: &AppContext) -> Option<String> {
+ fn text_for_range(&self, range_utf16: Range<usize>, cx: &AppContext) -> Option<String> {
Some(
self.buffer
.read(cx)
.read(cx)
- .text_for_range(range)
+ .text_for_range(OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end))
.collect(),
)
}
fn selected_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
- Some(self.selections.newest(cx).range())
+ let range = self.selections.newest::<OffsetUtf16>(cx).range();
+ Some(range.start.0..range.end.0)
}
- fn set_selected_text_range(&mut self, range: Range<usize>, cx: &mut ViewContext<Self>) {
- self.change_selections(None, cx, |selections| selections.select_ranges([range]));
+ fn set_selected_text_range(&mut self, range_utf16: Range<usize>, cx: &mut ViewContext<Self>) {
+ self.change_selections(None, cx, |selections| {
+ selections.select_ranges([OffsetUtf16(range_utf16.start)..OffsetUtf16(range_utf16.end)])
+ });
}
fn marked_text_range(&self, cx: &AppContext) -> Option<Range<usize>> {
let range = self.text_highlights::<InputComposition>(cx)?.1.get(0)?;
- Some(range.to_offset(&*self.buffer.read(cx).read(cx)))
+ let snapshot = self.buffer.read(cx).read(cx);
+ let range_utf16 =
+ range.start.to_offset_utf16(&snapshot)..range.end.to_offset_utf16(&snapshot);
+ Some(range_utf16.start.0..range_utf16.end.0)
}
fn unmark_text(&mut self, cx: &mut ViewContext<Self>) {
@@ -5906,34 +5912,36 @@ impl View for Editor {
fn replace_text_in_range(
&mut self,
- range: Option<Range<usize>>,
+ range_utf16: Option<Range<usize>>,
text: &str,
cx: &mut ViewContext<Self>,
) {
self.transact(cx, |this, cx| {
- if let Some(range) = range {
- this.set_selected_text_range(range, cx);
+ if let Some(range_utf16) = range_utf16.or_else(|| this.marked_text_range(cx)) {
+ this.set_selected_text_range(range_utf16, cx);
}
this.handle_input(text, cx);
+ this.unmark_text(cx);
});
}
fn replace_and_mark_text_in_range(
&mut self,
- range: Option<Range<usize>>,
+ range_utf16: Option<Range<usize>>,
text: &str,
- new_selected_range: Option<Range<usize>>,
+ new_selected_range_utf16: Option<Range<usize>>,
cx: &mut ViewContext<Self>,
) {
self.transact(cx, |this, cx| {
- let range = range.or_else(|| {
- let ranges = this.text_highlights::<InputComposition>(cx)?.1;
- let range = ranges.first()?;
- let snapshot = this.buffer.read(cx).read(cx);
- Some(range.to_offset(&*snapshot))
- });
- if let Some(range) = range {
- this.set_selected_text_range(range, cx);
+ if let Some(mut marked_range) = this.marked_text_range(cx) {
+ if let Some(relative_range_utf16) = range_utf16.as_ref() {
+ marked_range.end = marked_range.start + relative_range_utf16.end;
+ marked_range.start += relative_range_utf16.start;
+ }
+
+ this.set_selected_text_range(marked_range, cx);
+ } else if let Some(range_utf16) = range_utf16 {
+ this.set_selected_text_range(range_utf16, cx);
}
let selection = this.selections.newest_anchor();
@@ -5941,16 +5949,28 @@ impl View for Editor {
let snapshot = this.buffer.read(cx).read(cx);
selection.start.bias_left(&*snapshot)..selection.end.bias_right(&*snapshot)
};
- this.highlight_text::<InputComposition>(
- vec![marked_range],
- this.style(cx).composition_mark,
- cx,
- );
+
+ if text.is_empty() {
+ this.unmark_text(cx);
+ } else {
+ this.highlight_text::<InputComposition>(
+ vec![marked_range.clone()],
+ this.style(cx).composition_mark,
+ cx,
+ );
+ }
this.handle_input(text, cx);
- if let Some(new_selected_range) = new_selected_range {
- this.set_selected_text_range(new_selected_range, cx);
+ if let Some(new_selected_range) = new_selected_range_utf16 {
+ let snapshot = this.buffer.read(cx).read(cx);
+ let insertion_start = marked_range.start.to_offset_utf16(&snapshot).0;
+ drop(snapshot);
+ this.set_selected_text_range(
+ insertion_start + new_selected_range.start
+ ..insertion_start + new_selected_range.end,
+ cx,
+ );
}
});
}
@@ -1,10 +1,10 @@
-use super::{ExcerptId, MultiBufferSnapshot, ToOffset, ToPoint};
+use super::{ExcerptId, MultiBufferSnapshot, ToOffset, ToOffsetUtf16, ToPoint};
use std::{
cmp::Ordering,
ops::{Range, Sub},
};
use sum_tree::Bias;
-use text::{rope::TextDimension, Point};
+use text::{rope::TextDimension, OffsetUtf16, Point};
#[derive(Clone, Eq, PartialEq, Debug, Hash)]
pub struct Anchor {
@@ -89,6 +89,12 @@ impl ToOffset for Anchor {
}
}
+impl ToOffsetUtf16 for Anchor {
+ fn to_offset_utf16(&self, snapshot: &MultiBufferSnapshot) -> OffsetUtf16 {
+ self.summary(snapshot)
+ }
+}
+
impl ToPoint for Anchor {
fn to_point<'a>(&self, snapshot: &MultiBufferSnapshot) -> Point {
self.summary(snapshot)
@@ -1139,62 +1139,31 @@ extern "C" fn set_marked_text(
.to_str()
.unwrap();
- let window_state = get_window_state(this);
- let mut window_state = window_state.borrow_mut();
- if let Some(pending) = window_state.pending_key_event.as_mut() {
- pending.set_marked_text = Some((text.to_string(), selected_range, replacement_range));
- } else {
- drop(window_state);
- with_input_handler(this, |input_handler| {
- input_handler.replace_and_mark_text_in_range(
- replacement_range,
- text,
- selected_range,
- );
- });
- }
+ with_input_handler(this, |input_handler| {
+ input_handler.replace_and_mark_text_in_range(replacement_range, text, selected_range);
+ });
}
}
extern "C" fn unmark_text(this: &Object, _: Sel) {
- println!("unmark_text");
- let window_state = unsafe { get_window_state(this) };
- let mut window_state = window_state.borrow_mut();
- if let Some(pending) = window_state.pending_key_event.as_mut() {
- pending.unmark_text = true;
- pending.set_marked_text.take();
- } else {
- drop(window_state);
- with_input_handler(this, |input_handler| input_handler.finish_composition());
- }
+ with_input_handler(this, |input_handler| input_handler.finish_composition());
}
extern "C" fn attributed_substring_for_proposed_range(
this: &Object,
_: Sel,
range: NSRange,
- actual_range: *mut c_void,
+ _actual_range: *mut c_void,
) -> id {
+ println!("attributed_substring_for_proposed_range({:?})", range);
with_input_handler(this, |input_handler| {
- let actual_range = actual_range as *mut NSRange;
- if !actual_range.is_null() {
- unsafe { *actual_range = NSRange::invalid() };
- }
-
- let requested_range = range.to_range()?;
- if requested_range.is_empty() {
- return None;
- }
-
- let selected_range = input_handler.selected_text_range()?;
- let intersection = cmp::max(requested_range.start, selected_range.start)
- ..cmp::min(requested_range.end, selected_range.end);
- if intersection.start >= intersection.end {
+ let range = range.to_range()?;
+ if range.is_empty() {
return None;
}
+ let selected_text = input_handler.text_for_range(range)?;
unsafe {
- let selected_text = input_handler.text_for_range(intersection)?;
let string: id = msg_send![class!(NSAttributedString), alloc];
let string: id = msg_send![string, initWithString: ns_string(&selected_text)];
Some(string)
@@ -0,0 +1,50 @@
+use std::ops::{Add, AddAssign, Sub};
+
+#[derive(Copy, Clone, Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
+pub struct OffsetUtf16(pub usize);
+
+impl<'a> Add<&'a Self> for OffsetUtf16 {
+ type Output = Self;
+
+ fn add(self, other: &'a Self) -> Self::Output {
+ Self(self.0 + other.0)
+ }
+}
+
+impl Add for OffsetUtf16 {
+ type Output = Self;
+
+ fn add(self, other: Self) -> Self::Output {
+ Self(self.0 + other.0)
+ }
+}
+
+impl<'a> Sub<&'a Self> for OffsetUtf16 {
+ type Output = Self;
+
+ fn sub(self, other: &'a Self) -> Self::Output {
+ debug_assert!(*other <= self);
+ Self(self.0 - other.0)
+ }
+}
+
+impl Sub for OffsetUtf16 {
+ type Output = OffsetUtf16;
+
+ fn sub(self, other: Self) -> Self::Output {
+ debug_assert!(other <= self);
+ Self(self.0 - other.0)
+ }
+}
+
+impl<'a> AddAssign<&'a Self> for OffsetUtf16 {
+ fn add_assign(&mut self, other: &'a Self) {
+ self.0 += other.0;
+ }
+}
+
+impl AddAssign<Self> for OffsetUtf16 {
+ fn add_assign(&mut self, other: Self) {
+ self.0 += other.0;
+ }
+}