1#[cfg(not(feature = "std"))]
4use alloc::{
5 string::{String, ToString},
6 vec::Vec,
7};
8use core::{cmp, iter::once, ops::Range};
9use unicode_segmentation::UnicodeSegmentation;
10
11#[cfg(feature = "swash")]
12use crate::Color;
13use crate::{
14 Action, Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, BufferRef, Change, ChangeItem,
15 Cursor, Edit, FontSystem, LayoutRun, Motion, Selection, Shaping,
16};
17
18#[derive(Debug)]
20pub struct Editor<'buffer> {
21 buffer_ref: BufferRef<'buffer>,
22 cursor: Cursor,
23 cursor_x_opt: Option<i32>,
24 selection: Selection,
25 cursor_moved: bool,
26 auto_indent: bool,
27 tab_width: u16,
28 change: Option<Change>,
29 has_preedit_without_cursor: bool,
32 cursor_hidden_by_setting: bool,
34}
35
36fn cursor_glyph_opt(cursor: &Cursor, run: &LayoutRun) -> Option<(usize, f32)> {
37 if cursor.line == run.line_i {
38 for (glyph_i, glyph) in run.glyphs.iter().enumerate() {
39 if cursor.index == glyph.start {
40 return Some((glyph_i, 0.0));
41 } else if cursor.index > glyph.start && cursor.index < glyph.end {
42 let mut before = 0;
44 let mut total = 0;
45
46 let cluster = &run.text[glyph.start..glyph.end];
47 for (i, _) in cluster.grapheme_indices(true) {
48 if glyph.start + i < cursor.index {
49 before += 1;
50 }
51 total += 1;
52 }
53
54 let offset = glyph.w * (before as f32) / (total as f32);
55 return Some((glyph_i, offset));
56 }
57 }
58 match run.glyphs.last() {
59 Some(glyph) => {
60 if cursor.index == glyph.end {
61 return Some((run.glyphs.len(), 0.0));
62 }
63 }
64 None => {
65 return Some((0, 0.0));
66 }
67 }
68 }
69 None
70}
71
72fn cursor_position(cursor: &Cursor, run: &LayoutRun) -> Option<(i32, i32)> {
73 let (cursor_glyph, cursor_glyph_offset) = cursor_glyph_opt(cursor, run)?;
74 let x = match run.glyphs.get(cursor_glyph) {
75 Some(glyph) => {
76 if glyph.level.is_rtl() {
78 (glyph.x + glyph.w - cursor_glyph_offset) as i32
79 } else {
80 (glyph.x + cursor_glyph_offset) as i32
81 }
82 }
83 None => match run.glyphs.last() {
84 Some(glyph) => {
85 if glyph.level.is_rtl() {
87 glyph.x as i32
88 } else {
89 (glyph.x + glyph.w) as i32
90 }
91 }
92 None => {
93 0
95 }
96 },
97 };
98
99 Some((x, run.line_top as i32))
100}
101
102impl<'buffer> Editor<'buffer> {
103 pub fn new(buffer: impl Into<BufferRef<'buffer>>) -> Self {
105 Self {
106 buffer_ref: buffer.into(),
107 cursor: Cursor::default(),
108 cursor_x_opt: None,
109 selection: Selection::None,
110 cursor_moved: false,
111 auto_indent: false,
112 tab_width: 4,
113 change: None,
114 has_preedit_without_cursor: false,
115 cursor_hidden_by_setting: false,
116 }
117 }
118
119 #[cfg(feature = "swash")]
121 pub fn draw<F>(
122 &self,
123 font_system: &mut FontSystem,
124 cache: &mut crate::SwashCache,
125 text_color: Color,
126 cursor_color: Color,
127 selection_color: Color,
128 selected_text_color: Color,
129 mut f: F,
130 ) where
131 F: FnMut(i32, i32, u32, u32, Color),
132 {
133 let selection_bounds = self.selection_bounds();
134 self.with_buffer(|buffer| {
135 let line_height = buffer.metrics().line_height;
136 for run in buffer.layout_runs() {
137 let line_i = run.line_i;
138 let line_y = run.line_y;
139 let line_top = run.line_top;
140
141 if let Some((start, end)) = selection_bounds {
143 if line_i >= start.line && line_i <= end.line {
144 let mut range_opt = None;
145 for glyph in run.glyphs.iter() {
146 let cluster = &run.text[glyph.start..glyph.end];
148 let total = cluster.grapheme_indices(true).count();
149 let mut c_x = glyph.x;
150 let c_w = glyph.w / total as f32;
151 for (i, c) in cluster.grapheme_indices(true) {
152 let c_start = glyph.start + i;
153 let c_end = glyph.start + i + c.len();
154 if (start.line != line_i || c_end > start.index)
155 && (end.line != line_i || c_start < end.index)
156 {
157 range_opt = match range_opt.take() {
158 Some((min, max)) => Some((
159 cmp::min(min, c_x as i32),
160 cmp::max(max, (c_x + c_w) as i32),
161 )),
162 None => Some((c_x as i32, (c_x + c_w) as i32)),
163 };
164 } else if let Some((min, max)) = range_opt.take() {
165 f(
166 min,
167 line_top as i32,
168 cmp::max(0, max - min) as u32,
169 line_height as u32,
170 selection_color,
171 );
172 }
173 c_x += c_w;
174 }
175 }
176
177 if run.glyphs.is_empty() && end.line > line_i {
178 range_opt = Some((0, buffer.size().0 as i32));
180 }
181
182 if let Some((mut min, mut max)) = range_opt.take() {
183 if end.line > line_i {
184 if run.rtl {
186 min = 0;
187 } else {
188 max = buffer.size().0 as i32;
189 }
190 }
191 f(
192 min,
193 line_top as i32,
194 cmp::max(0, max - min) as u32,
195 line_height as u32,
196 selection_color,
197 );
198 }
199 }
200 }
201
202 let cursor_hidden = self.cursor_hidden_by_setting
204 || self.has_preedit_without_cursor
205 || self.has_selection();
206
207 if !cursor_hidden {
208 if let Some((x, y)) = cursor_position(&self.cursor, &run) {
209 f(x, y, 1, line_height as u32, cursor_color);
210 }
211 }
212
213 for glyph in run.glyphs.iter() {
214 let physical_glyph = glyph.physical((0., 0.), 1.0);
215
216 let mut glyph_color = match glyph.color_opt {
217 Some(some) => some,
218 None => text_color,
219 };
220 if text_color != selected_text_color {
221 if let Some((start, end)) = selection_bounds {
222 if line_i >= start.line
223 && line_i <= end.line
224 && (start.line != line_i || glyph.end > start.index)
225 && (end.line != line_i || glyph.start < end.index)
226 {
227 glyph_color = selected_text_color;
228 }
229 }
230 }
231
232 cache.with_pixels(
233 font_system,
234 physical_glyph.cache_key,
235 glyph_color,
236 |x, y, color| {
237 f(
238 physical_glyph.x + x,
239 line_y as i32 + physical_glyph.y + y,
240 1,
241 1,
242 color,
243 );
244 },
245 );
246 }
247 }
248 });
249 }
250}
251
252impl<'buffer> Edit<'buffer> for Editor<'buffer> {
253 fn buffer_ref(&self) -> &BufferRef<'buffer> {
254 &self.buffer_ref
255 }
256
257 fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer> {
258 &mut self.buffer_ref
259 }
260
261 fn cursor(&self) -> Cursor {
262 self.cursor
263 }
264
265 fn set_cursor(&mut self, cursor: Cursor) {
266 if self.cursor != cursor {
267 self.cursor = cursor;
268 self.cursor_moved = true;
269 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
270 }
271 }
272
273 fn set_cursor_hidden(&mut self, hidden: bool) {
274 self.cursor_hidden_by_setting = hidden;
275 self.set_redraw(true);
276 }
277
278 fn selection(&self) -> Selection {
279 self.selection
280 }
281
282 fn set_selection(&mut self, selection: Selection) {
283 if self.selection != selection {
284 self.selection = selection;
285 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
286 }
287 }
288
289 fn auto_indent(&self) -> bool {
290 self.auto_indent
291 }
292
293 fn set_auto_indent(&mut self, auto_indent: bool) {
294 self.auto_indent = auto_indent;
295 }
296
297 fn tab_width(&self) -> u16 {
298 self.tab_width
299 }
300
301 fn set_tab_width(&mut self, tab_width: u16) {
302 if tab_width == 0 {
304 return;
305 }
306 if self.tab_width != tab_width {
307 self.tab_width = tab_width;
308 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
309 }
310 }
311
312 fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool) {
313 if self.cursor_moved {
314 let cursor = self.cursor;
315 self.with_buffer_mut(|buffer| buffer.shape_until_cursor(font_system, cursor, prune));
316 self.cursor_moved = false;
317 } else {
318 self.with_buffer_mut(|buffer| buffer.shape_until_scroll(font_system, prune));
319 }
320 }
321
322 fn delete_range(&mut self, start: Cursor, end: Cursor) {
323 let change_item = self.with_buffer_mut(|buffer| {
324 let mut change_lines = Vec::new();
326
327 let end_line_opt = if end.line > start.line {
329 let after = buffer.lines[end.line].split_off(end.index);
331
332 let removed = buffer.lines.remove(end.line);
334 change_lines.insert(0, removed.text().to_string());
335
336 Some(after)
337 } else {
338 None
339 };
340
341 for line_i in (start.line + 1..end.line).rev() {
343 let removed = buffer.lines.remove(line_i);
344 change_lines.insert(0, removed.text().to_string());
345 }
346
347 {
349 let after_opt = if start.line == end.line {
351 Some(buffer.lines[start.line].split_off(end.index))
352 } else {
353 None
354 };
355
356 let removed = buffer.lines[start.line].split_off(start.index);
358 change_lines.insert(0, removed.text().to_string());
359
360 if let Some(after) = after_opt {
362 buffer.lines[start.line].append(after);
363 }
364
365 if let Some(end_line) = end_line_opt {
367 buffer.lines[start.line].append(end_line);
368 }
369 }
370
371 ChangeItem {
372 start,
373 end,
374 text: change_lines.join("\n"),
375 insert: false,
376 }
377 });
378
379 if let Some(ref mut change) = self.change {
380 change.items.push(change_item);
381 }
382 }
383
384 fn insert_at(
385 &mut self,
386 mut cursor: Cursor,
387 data: &str,
388 attrs_list: Option<AttrsList>,
389 ) -> Cursor {
390 let mut remaining_split_len = data.len();
391 if remaining_split_len == 0 {
392 return cursor;
393 }
394
395 let change_item = self.with_buffer_mut(|buffer| {
396 let start = cursor;
398
399 while cursor.line >= buffer.lines.len() {
401 let line = BufferLine::new(
402 String::new(),
403 AttrsList::new(attrs_list.as_ref().map_or_else(
404 || {
405 buffer
406 .lines
407 .last()
408 .map_or(Attrs::new(), |line| line.attrs_list().defaults())
409 },
410 |x| x.defaults(),
411 )),
412 Shaping::Advanced,
413 );
414 buffer.lines.push(line);
415 }
416
417 let line: &mut BufferLine = &mut buffer.lines[cursor.line];
418 let insert_line = cursor.line + 1;
419
420 let after: BufferLine = line.split_off(cursor.index);
422 let after_len = after.text().len();
423
424 let mut final_attrs = attrs_list.unwrap_or_else(|| {
426 AttrsList::new(line.attrs_list().get_span(cursor.index.saturating_sub(1)))
427 });
428
429 let addendum = once("").filter(|_| data.ends_with('\n'));
432 let mut lines_iter = data.split_inclusive('\n').chain(addendum);
433 if let Some(data_line) = lines_iter.next() {
434 let mut these_attrs = final_attrs.split_off(data_line.len());
435 remaining_split_len -= data_line.len();
436 core::mem::swap(&mut these_attrs, &mut final_attrs);
437 line.append(BufferLine::new(
438 data_line
439 .strip_suffix(char::is_control)
440 .unwrap_or(data_line),
441 these_attrs,
442 Shaping::Advanced,
443 ));
444 } else {
445 panic!("str::lines() did not yield any elements");
446 }
447 if let Some(data_line) = lines_iter.next_back() {
448 remaining_split_len -= data_line.len();
449 let mut tmp = BufferLine::new(
450 data_line
451 .strip_suffix(char::is_control)
452 .unwrap_or(data_line),
453 final_attrs.split_off(remaining_split_len),
454 Shaping::Advanced,
455 );
456 tmp.append(after);
457 buffer.lines.insert(insert_line, tmp);
458 cursor.line += 1;
459 } else {
460 line.append(after);
461 }
462 for data_line in lines_iter.rev() {
463 remaining_split_len -= data_line.len();
464 let tmp = BufferLine::new(
465 data_line
466 .strip_suffix(char::is_control)
467 .unwrap_or(data_line),
468 final_attrs.split_off(remaining_split_len),
469 Shaping::Advanced,
470 );
471 buffer.lines.insert(insert_line, tmp);
472 cursor.line += 1;
473 }
474
475 assert_eq!(remaining_split_len, 0);
476
477 cursor.index = buffer.lines[cursor.line].text().len() - after_len;
479
480 ChangeItem {
481 start,
482 end: cursor,
483 text: data.to_string(),
484 insert: true,
485 }
486 });
487
488 if let Some(ref mut change) = self.change {
489 change.items.push(change_item);
490 }
491
492 cursor
493 }
494
495 fn copy_selection(&self) -> Option<String> {
496 let (start, end) = self.selection_bounds()?;
497 self.with_buffer(|buffer| {
498 let mut selection = String::new();
499 {
501 if start.line == end.line {
503 selection.push_str(&buffer.lines[start.line].text()[start.index..end.index]);
504 } else {
505 selection.push_str(&buffer.lines[start.line].text()[start.index..]);
506 selection.push('\n');
507 }
508 }
509
510 for line_i in start.line + 1..end.line {
512 selection.push_str(buffer.lines[line_i].text());
513 selection.push('\n');
514 }
515
516 if end.line > start.line {
518 selection.push_str(&buffer.lines[end.line].text()[..end.index]);
520 }
521
522 Some(selection)
523 })
524 }
525
526 fn delete_selection(&mut self) -> bool {
527 let (start, end) = match self.selection_bounds() {
528 Some(some) => some,
529 None => return false,
530 };
531
532 self.cursor = start;
534
535 self.selection = Selection::None;
537
538 self.delete_range(start, end);
540
541 true
542 }
543
544 fn apply_change(&mut self, change: &Change) -> bool {
545 match self.change.take() {
547 Some(pending) => {
548 if !pending.items.is_empty() {
549 log::warn!("pending change caused apply_change to be ignored!");
551 self.change = Some(pending);
552 return false;
553 }
554 }
555 None => {}
556 }
557
558 for item in change.items.iter() {
559 if item.insert {
561 self.cursor = self.insert_at(item.start, &item.text, None);
562 } else {
563 self.cursor = item.start;
564 self.delete_range(item.start, item.end);
565 }
566 }
567 true
568 }
569
570 fn start_change(&mut self) {
571 if self.change.is_none() {
572 self.change = Some(Change::default());
573 }
574 }
575
576 fn finish_change(&mut self) -> Option<Change> {
577 self.change.take()
578 }
579
580 fn preedit_range(&self) -> Option<Range<usize>> {
581 self.with_buffer(|buffer| buffer.lines[self.cursor.line].preedit_range())
582 }
583
584 fn preedit_text(&self) -> Option<String> {
585 self.with_buffer(|buffer| {
586 buffer.lines[self.cursor.line]
587 .preedit_text()
588 .map(Into::into)
589 })
590 }
591
592 fn action(&mut self, font_system: &mut FontSystem, action: Action) {
593 let old_cursor = self.cursor;
594
595 match action {
596 Action::Motion { motion, select } => {
597 let cursor = self.cursor;
598 if select {
599 if self.selection == Selection::None {
600 self.selection = Selection::Normal(self.cursor);
601 }
602 } else if let Some((start, end)) = self.selection_bounds() {
603 if start.line != end.line || start.index != end.index {
604 let new_cursor = match motion {
605 Motion::Previous => Some(start),
607 Motion::Next => Some(end),
608 Motion::Left => self
609 .with_buffer_mut(|buffer| {
610 buffer
611 .line_shape(font_system, cursor.line)
612 .map(|shape| shape.rtl)
613 })
614 .map(|rtl| if rtl { end } else { start }),
615 Motion::Right => self
616 .with_buffer_mut(|buffer| {
617 buffer
618 .line_shape(font_system, cursor.line)
619 .map(|shape| shape.rtl)
620 })
621 .map(|rtl| if rtl { start } else { end }),
622 _ => None,
623 };
624 if let Some(new_cursor) = new_cursor {
625 self.cursor = new_cursor;
626 self.cursor_x_opt = None;
627 self.cursor_moved = true;
628 self.selection = Selection::None;
629 self.set_redraw(true);
630 return;
631 }
632 }
633 self.selection = Selection::None;
634 }
635
636 let cursor_x_opt = self.cursor_x_opt;
637 if let Some((new_cursor, new_cursor_x_opt)) = self.with_buffer_mut(|buffer| {
638 buffer.cursor_motion(font_system, cursor, cursor_x_opt, motion)
639 }) {
640 self.cursor = new_cursor;
641 self.cursor_x_opt = new_cursor_x_opt;
642 }
643 }
644 Action::Escape => {
645 match self.selection {
646 Selection::None => {}
647 _ => self.with_buffer_mut(|buffer| buffer.set_redraw(true)),
648 }
649 self.selection = Selection::None;
650 }
651 Action::SelectAll => {
652 self.action(
653 font_system,
654 Action::Motion {
655 motion: Motion::DocumentStart,
656 select: false,
657 },
658 );
659 self.action(
660 font_system,
661 Action::Motion {
662 motion: Motion::DocumentEnd,
663 select: true,
664 },
665 );
666 }
667 Action::Insert(character) => {
668 if character.is_control() && !['\t', '\n', '\u{92}'].contains(&character) {
669 log::debug!("Refusing to insert control character {:?}", character);
671 } else if character == '\n' {
672 self.action(font_system, Action::Enter);
673 } else {
674 let mut str_buf = [0u8; 8];
675 let str_ref = character.encode_utf8(&mut str_buf);
676 self.insert_string(str_ref, None);
677 }
678 }
679 Action::Enter => {
680 if self.auto_indent {
682 let mut string = String::from("\n");
683 self.with_buffer(|buffer| {
684 let line = &buffer.lines[self.cursor.line];
685 let text = line.text();
686 for c in text.chars() {
687 if c.is_whitespace() {
688 string.push(c);
689 } else {
690 break;
691 }
692 }
693 });
694 self.insert_string(&string, None);
695 } else {
696 self.insert_string("\n", None);
697 }
698
699 let line_i = self.cursor.line;
701 self.with_buffer_mut(|buffer| {
702 buffer.line_layout(font_system, line_i);
703 });
704 }
705 Action::Backspace => {
706 if self.delete_selection() {
707 } else {
709 let end = self.cursor;
711
712 if self.cursor.index > 0 {
713 self.cursor.index = self.with_buffer(|buffer| {
715 buffer.lines[self.cursor.line].text()[..self.cursor.index]
716 .char_indices()
717 .next_back()
718 .map_or(0, |(i, _)| i)
719 });
720 } else if self.cursor.line > 0 {
721 self.cursor.line -= 1;
723 self.cursor.index =
724 self.with_buffer(|buffer| buffer.lines[self.cursor.line].text().len());
725 }
726
727 if self.cursor != end {
728 self.delete_range(self.cursor, end);
730 }
731 }
732 }
733 Action::DeleteStartOfWord => {
734 if self.delete_selection() {
735 } else {
737 self.action(
738 font_system,
739 Action::Motion {
740 motion: Motion::PreviousWord,
741 select: true,
742 },
743 );
744 self.delete_selection();
745 }
746 }
747 Action::Delete => {
748 if self.delete_selection() {
749 } else {
751 let mut start = self.cursor;
753 let mut end = self.cursor;
754
755 self.with_buffer(|buffer| {
756 if start.index < buffer.lines[start.line].text().len() {
757 let line = &buffer.lines[start.line];
758
759 let range_opt = line
760 .text()
761 .grapheme_indices(true)
762 .take_while(|(i, _)| *i <= start.index)
763 .last()
764 .map(|(i, c)| i..(i + c.len()));
765
766 if let Some(range) = range_opt {
767 start.index = range.start;
768 end.index = range.end;
769 }
770 } else if start.line + 1 < buffer.lines.len() {
771 end.line += 1;
772 end.index = 0;
773 }
774 });
775
776 if start != end {
777 self.cursor = start;
778 self.delete_range(start, end);
779 }
780 }
781 }
782 Action::DeleteEndOfWord => {
783 if self.delete_selection() {
784 } else {
786 self.action(
787 font_system,
788 Action::Motion {
789 motion: Motion::NextWord,
790 select: true,
791 },
792 );
793 self.delete_selection();
794 }
795 }
796 Action::Indent => {
797 let (start, end) = match self.selection_bounds() {
799 Some(some) => some,
800 None => (self.cursor, self.cursor),
801 };
802
803 let tab_width: usize = self.tab_width.into();
805 for line_i in start.line..=end.line {
806 let mut after_whitespace = 0;
808 let mut required_indent = 0;
809 self.with_buffer(|buffer| {
810 let line = &buffer.lines[line_i];
811 let text = line.text();
812 after_whitespace = text.len();
814 for (count, (index, c)) in text.char_indices().enumerate() {
815 if !c.is_whitespace() {
816 after_whitespace = index;
817 required_indent = tab_width - (count % tab_width);
818 break;
819 }
820 }
821 });
822
823 if required_indent == 0 {
825 required_indent = tab_width;
826 }
827
828 self.insert_at(
829 Cursor::new(line_i, after_whitespace),
830 &" ".repeat(required_indent),
831 None,
832 );
833
834 if self.cursor.line == line_i {
836 if self.cursor.index < after_whitespace {
838 self.cursor.index = after_whitespace;
839 }
840 self.cursor.index += required_indent;
841 }
842
843 match self.selection {
845 Selection::None => {}
846 Selection::Normal(ref mut select)
847 | Selection::Line(ref mut select)
848 | Selection::Word(ref mut select) => {
849 if select.line == line_i && select.index >= after_whitespace {
850 select.index += required_indent;
851 }
852 }
853 }
854
855 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
857 }
858 }
859 Action::Unindent => {
860 let (start, end) = match self.selection_bounds() {
862 Some(some) => some,
863 None => (self.cursor, self.cursor),
864 };
865
866 let tab_width: usize = self.tab_width.into();
868 for line_i in start.line..=end.line {
869 let mut last_indent = 0;
871 let mut after_whitespace = 0;
872 self.with_buffer(|buffer| {
873 let line = &buffer.lines[line_i];
874 let text = line.text();
875 after_whitespace = text.len();
877 for (count, (index, c)) in text.char_indices().enumerate() {
878 if !c.is_whitespace() {
879 after_whitespace = index;
880 break;
881 }
882 if count % tab_width == 0 {
883 last_indent = index;
884 }
885 }
886 });
887
888 if last_indent == after_whitespace {
890 continue;
891 }
892
893 self.delete_range(
895 Cursor::new(line_i, last_indent),
896 Cursor::new(line_i, after_whitespace),
897 );
898
899 if self.cursor.line == line_i && self.cursor.index > last_indent {
901 self.cursor.index -= after_whitespace - last_indent;
902 }
903
904 match self.selection {
906 Selection::None => {}
907 Selection::Normal(ref mut select)
908 | Selection::Line(ref mut select)
909 | Selection::Word(ref mut select) => {
910 if select.line == line_i && select.index > last_indent {
911 select.index -= after_whitespace - last_indent;
912 }
913 }
914 }
915
916 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
918 }
919 }
920 Action::Click { x, y, select } => {
921 if select {
922 if self.selection == Selection::None {
923 self.selection = Selection::Normal(self.cursor);
924 }
925 } else {
926 self.selection = Selection::None;
927 }
928
929 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
930 {
931 if new_cursor != self.cursor {
932 self.cursor = new_cursor;
933 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
934 }
935 }
936 }
937 Action::DoubleClick { x, y } => {
938 self.set_selection(Selection::None);
939
940 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
941 {
942 if new_cursor != self.cursor {
943 self.cursor = new_cursor;
944 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
945 }
946 self.selection = Selection::Word(self.cursor);
947 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
948 }
949 }
950 Action::TripleClick { x, y } => {
951 self.set_selection(Selection::None);
952
953 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
954 {
955 if new_cursor != self.cursor {
956 self.cursor = new_cursor;
957 }
958 self.selection = Selection::Line(self.cursor);
959 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
960 }
961 }
962 Action::Drag { x, y } => {
963 if self.selection == Selection::None {
964 self.selection = Selection::Normal(self.cursor);
965 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
966 }
967
968 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
969 {
970 if new_cursor != self.cursor {
971 self.cursor = new_cursor;
972 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
973 }
974 }
975 }
976 Action::Scroll { lines } => {
977 self.with_buffer_mut(|buffer| {
978 let mut scroll = buffer.scroll();
979 scroll.layout += lines;
980 buffer.set_scroll(scroll);
981 });
982 }
983 Action::SetPreedit {
984 preedit,
985 cursor,
986 attrs,
987 } => {
988 self.selection = Selection::None;
989 let mut self_cursor = self.cursor;
990
991 self.with_buffer_mut(|buffer| {
993 let line: &mut BufferLine = &mut buffer.lines[self_cursor.line];
994 if let Some(range) = line.preedit_range() {
995 let end = line.split_off(range.end);
996 line.split_off(range.start);
997 line.append(end);
998 self_cursor.index = range.start;
999 }
1000 });
1001 self.cursor = self_cursor;
1002
1003 if !preedit.is_empty() {
1004 let new_attrs = if let Some(attrs) = attrs {
1005 AttrsList::new(attrs.as_attrs().preedit(true))
1006 } else {
1007 self.with_buffer(|buffer| {
1008 let attrs_at_cursor = buffer.lines[self_cursor.line]
1009 .attrs_list()
1010 .get_span(self_cursor.index);
1011 AttrsList::new(
1012 attrs_at_cursor
1013 .preedit(true)
1014 .color(Color::rgb(128, 128, 128)),
1015 )
1016 })
1017 };
1018 self.insert_string(&preedit, Some(new_attrs));
1019 if let Some((start, end)) = cursor {
1020 let end_delta = preedit.len().saturating_sub(end);
1021 self.cursor.index = self.cursor.index.saturating_sub(end_delta);
1022 if start != end {
1023 let start_delta = preedit.len().saturating_sub(start);
1024 let mut select = self.cursor;
1025 select.index = select.index.saturating_sub(start_delta);
1026 self.selection = Selection::Normal(select);
1027 }
1028 }
1029 }
1030 self.has_preedit_without_cursor = !preedit.is_empty() && cursor.is_none();
1031 self.set_redraw(true);
1032 }
1033 }
1034
1035 if old_cursor != self.cursor {
1036 self.cursor_moved = true;
1037 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
1038
1039 }
1055 }
1056
1057 fn cursor_position(&self) -> Option<(i32, i32)> {
1058 self.with_buffer(|buffer| {
1059 buffer
1060 .layout_runs()
1061 .find_map(|run| cursor_position(&self.cursor, &run))
1062 })
1063 }
1064}
1065
1066impl<'font_system, 'buffer> BorrowedWithFontSystem<'font_system, Editor<'buffer>> {
1067 #[cfg(feature = "swash")]
1068 pub fn draw<F>(
1069 &mut self,
1070 cache: &mut crate::SwashCache,
1071 text_color: Color,
1072 cursor_color: Color,
1073 selection_color: Color,
1074 selected_text_color: Color,
1075 f: F,
1076 ) where
1077 F: FnMut(i32, i32, u32, u32, Color),
1078 {
1079 self.inner.draw(
1080 self.font_system,
1081 cache,
1082 text_color,
1083 cursor_color,
1084 selection_color,
1085 selected_text_color,
1086 f,
1087 );
1088 }
1089}