1#[cfg(not(feature = "std"))]
4use alloc::{
5 string::{String, ToString},
6 vec::Vec,
7};
8use core::cmp;
9
10use unicode_segmentation::UnicodeSegmentation;
11
12use crate::{
13 render_decoration, Action, Attrs, AttrsList, BorrowedWithFontSystem, BufferLine, BufferRef,
14 Change, ChangeItem, Color, Cursor, Edit, FontSystem, LayoutRun, LineEnding, LineIter, Renderer,
15 Selection, Shaping,
16};
17
18#[derive(Debug, Clone)]
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 change: Option<Change>,
28}
29
30fn cursor_glyph_opt(cursor: &Cursor, run: &LayoutRun) -> Option<(usize, f32)> {
31 if cursor.line == run.line_i {
32 for (glyph_i, glyph) in run.glyphs.iter().enumerate() {
33 if cursor.index == glyph.start {
34 return Some((glyph_i, 0.0));
35 } else if cursor.index > glyph.start && cursor.index < glyph.end {
36 let mut before = 0;
38 let mut total = 0;
39
40 let cluster = &run.text[glyph.start..glyph.end];
41 for (i, _) in cluster.grapheme_indices(true) {
42 if glyph.start + i < cursor.index {
43 before += 1;
44 }
45 total += 1;
46 }
47
48 let offset = glyph.w * (before as f32) / (total as f32);
49 return Some((glyph_i, offset));
50 }
51 }
52 match run.glyphs.last() {
53 Some(glyph) => {
54 if cursor.index == glyph.end {
55 return Some((run.glyphs.len(), 0.0));
56 }
57 }
58 None => {
59 return Some((0, 0.0));
60 }
61 }
62 }
63 None
64}
65
66fn cursor_position(cursor: &Cursor, run: &LayoutRun) -> Option<(i32, i32)> {
67 let (cursor_glyph, cursor_glyph_offset) = cursor_glyph_opt(cursor, run)?;
68 let x = run.glyphs.get(cursor_glyph).map_or_else(
69 || {
70 run.glyphs.last().map_or(0, |glyph| {
71 if glyph.level.is_rtl() {
72 glyph.x as i32
73 } else {
74 (glyph.x + glyph.w) as i32
75 }
76 })
77 },
78 |glyph| {
79 if glyph.level.is_rtl() {
80 (glyph.x + glyph.w - cursor_glyph_offset) as i32
81 } else {
82 (glyph.x + cursor_glyph_offset) as i32
83 }
84 },
85 );
86
87 Some((x, run.line_top as i32))
88}
89
90impl<'buffer> Editor<'buffer> {
91 pub fn new(buffer: impl Into<BufferRef<'buffer>>) -> Self {
93 Self {
94 buffer_ref: buffer.into(),
95 cursor: Cursor::default(),
96 cursor_x_opt: None,
97 selection: Selection::None,
98 cursor_moved: false,
99 auto_indent: false,
100 change: None,
101 }
102 }
103
104 #[cfg(feature = "swash")]
106 #[allow(clippy::too_many_arguments)]
107 pub fn draw<F>(
108 &self,
109 font_system: &mut FontSystem,
110 cache: &mut crate::SwashCache,
111 text_color: Color,
112 cursor_color: Color,
113 selection_color: Color,
114 selected_text_color: Color,
115 callback: F,
116 ) where
117 F: FnMut(i32, i32, u32, u32, Color),
118 {
119 let mut renderer = crate::LegacyRenderer {
120 font_system,
121 cache,
122 callback,
123 };
124 self.render(
125 &mut renderer,
126 text_color,
127 cursor_color,
128 selection_color,
129 selected_text_color,
130 );
131 }
132
133 pub fn render<R: Renderer>(
134 &self,
135 renderer: &mut R,
136 text_color: Color,
137 cursor_color: Color,
138 selection_color: Color,
139 selected_text_color: Color,
140 ) {
141 let selection_bounds = self.selection_bounds();
142 self.with_buffer(|buffer| {
143 for run in buffer.layout_runs() {
144 let line_i = run.line_i;
145 let line_y = run.line_y;
146 let line_top = run.line_top;
147 let line_height = run.line_height;
148
149 if let Some((start, end)) = selection_bounds {
151 if line_i >= start.line && line_i <= end.line {
152 let mut range_opt = None;
153 for glyph in run.glyphs {
154 let cluster = &run.text[glyph.start..glyph.end];
156 let total = cluster.grapheme_indices(true).count();
157 let mut c_x = glyph.x;
158 let c_w = glyph.w / total as f32;
159 for (i, c) in cluster.grapheme_indices(true) {
160 let c_start = glyph.start + i;
161 let c_end = glyph.start + i + c.len();
162 if (start.line != line_i || c_end > start.index)
163 && (end.line != line_i || c_start < end.index)
164 {
165 range_opt = match range_opt.take() {
166 Some((min, max)) => Some((
167 cmp::min(min, c_x as i32),
168 cmp::max(max, (c_x + c_w) as i32),
169 )),
170 None => Some((c_x as i32, (c_x + c_w) as i32)),
171 };
172 } else if let Some((min, max)) = range_opt.take() {
173 renderer.rectangle(
174 min,
175 line_top as i32,
176 cmp::max(0, max - min) as u32,
177 line_height as u32,
178 selection_color,
179 );
180 }
181 c_x += c_w;
182 }
183 }
184
185 if run.glyphs.is_empty() && end.line > line_i {
186 range_opt = Some((0, buffer.size().0.unwrap_or(0.0) as i32));
188 }
189
190 if let Some((mut min, mut max)) = range_opt.take() {
191 if end.line > line_i {
192 if run.rtl {
194 min = 0;
195 } else {
196 max = buffer.size().0.unwrap_or(0.0) as i32;
197 }
198 }
199 renderer.rectangle(
200 min,
201 line_top as i32,
202 cmp::max(0, max - min) as u32,
203 line_height as u32,
204 selection_color,
205 );
206 }
207 }
208 }
209
210 if let Some((x, y)) = cursor_position(&self.cursor, &run) {
212 renderer.rectangle(x, y, 1, line_height as u32, cursor_color);
213 }
214
215 render_decoration(renderer, &run, text_color);
216 for glyph in run.glyphs {
217 let physical_glyph = glyph.physical((0., line_y), 1.0);
218
219 let mut glyph_color = glyph.color_opt.map_or(text_color, |some| some);
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 renderer.glyph(physical_glyph, glyph_color);
233 }
234 }
235 });
236 }
237}
238
239impl<'buffer> Edit<'buffer> for Editor<'buffer> {
240 fn buffer_ref(&self) -> &BufferRef<'buffer> {
241 &self.buffer_ref
242 }
243
244 fn buffer_ref_mut(&mut self) -> &mut BufferRef<'buffer> {
245 &mut self.buffer_ref
246 }
247
248 fn cursor(&self) -> Cursor {
249 self.cursor
250 }
251
252 fn set_cursor(&mut self, cursor: Cursor) {
253 if self.cursor != cursor {
254 self.cursor = cursor;
255 self.cursor_moved = true;
256 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
257 }
258 }
259
260 fn selection(&self) -> Selection {
261 self.selection
262 }
263
264 fn set_selection(&mut self, selection: Selection) {
265 if self.selection != selection {
266 self.selection = selection;
267 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
268 }
269 }
270
271 fn auto_indent(&self) -> bool {
272 self.auto_indent
273 }
274
275 fn set_auto_indent(&mut self, auto_indent: bool) {
276 self.auto_indent = auto_indent;
277 }
278
279 fn tab_width(&self) -> u16 {
280 self.with_buffer(super::super::buffer::Buffer::tab_width)
281 }
282
283 fn set_tab_width(&mut self, font_system: &mut FontSystem, tab_width: u16) {
284 self.with_buffer_mut(|buffer| buffer.set_tab_width(font_system, tab_width));
285 }
286
287 fn shape_as_needed(&mut self, font_system: &mut FontSystem, prune: bool) {
288 if self.cursor_moved {
289 let cursor = self.cursor;
290 self.with_buffer_mut(|buffer| buffer.shape_until_cursor(font_system, cursor, prune));
291 self.cursor_moved = false;
292 } else {
293 self.with_buffer_mut(|buffer| buffer.shape_until_scroll(font_system, prune));
294 }
295 }
296
297 fn delete_range(&mut self, start: Cursor, end: Cursor) {
298 let change_item = self.with_buffer_mut(|buffer| {
299 let mut change_lines = Vec::new();
301
302 let end_line_opt = if end.line > start.line {
304 let after = buffer.lines[end.line].split_off(end.index);
306
307 let removed = buffer.lines.remove(end.line);
309 change_lines.insert(0, removed);
310
311 Some(after)
312 } else {
313 None
314 };
315
316 for line_i in (start.line + 1..end.line).rev() {
318 let removed = buffer.lines.remove(line_i);
319 change_lines.insert(0, removed);
320 }
321
322 {
324 let line = &mut buffer.lines[start.line];
325
326 let after_opt = if start.line == end.line {
328 Some(line.split_off(end.index))
329 } else {
330 None
331 };
332
333 let removed = line.split_off(start.index);
335 change_lines.insert(0, removed);
336
337 if let Some(after) = after_opt {
339 line.append(&after);
340 }
341
342 if let Some(mut end_line) = end_line_opt {
344 if end_line.ending() == LineEnding::None {
346 end_line.set_ending(line.ending());
347 }
348 line.append(&end_line);
349 }
350 }
351
352 let mut text = String::new();
353 let mut last_ending: Option<LineEnding> = None;
354 for line in change_lines {
355 if let Some(ending) = last_ending {
356 text.push_str(ending.as_str());
357 }
358 text.push_str(line.text());
359 last_ending = Some(line.ending());
360 }
361
362 ChangeItem {
363 start,
364 end,
365 text,
366 insert: false,
367 }
368 });
369
370 if let Some(ref mut change) = self.change {
371 change.items.push(change_item);
372 }
373 }
374
375 fn insert_at(
376 &mut self,
377 mut cursor: Cursor,
378 data: &str,
379 attrs_list: Option<AttrsList>,
380 ) -> Cursor {
381 let mut remaining_split_len = data.len();
382 if remaining_split_len == 0 {
383 return cursor;
384 }
385
386 let change_item = self.with_buffer_mut(|buffer| {
387 let start = cursor;
389
390 while cursor.line >= buffer.lines.len() {
392 let mut last_ending = LineEnding::None;
394 if let Some(last_line) = buffer.lines.last_mut() {
395 last_ending = last_line.ending();
396 if last_ending == LineEnding::None {
398 last_line.set_ending(LineEnding::default());
399 }
400 }
401 let line = BufferLine::new(
402 String::new(),
403 last_ending,
404 AttrsList::new(&attrs_list.as_ref().map_or_else(
405 || {
406 buffer
407 .lines
408 .last()
409 .map_or_else(Attrs::new, |line| line.attrs_list().defaults())
410 },
411 |x| x.defaults(),
412 )),
413 Shaping::Advanced,
414 );
415 buffer.lines.push(line);
416 }
417
418 let line: &mut BufferLine = &mut buffer.lines[cursor.line];
419 let insert_line = cursor.line + 1;
420
421 let after: BufferLine = line.split_off(cursor.index);
423 let after_len = after.text().len();
424
425 let mut final_attrs = attrs_list.unwrap_or_else(|| {
427 AttrsList::new(&line.attrs_list().get_span(cursor.index.saturating_sub(1)))
428 });
429
430 let mut lines: Vec<_> = LineIter::new(data).collect();
432 if lines.last().map(|line| line.1).unwrap_or(LineEnding::None) != LineEnding::None {
434 lines.push((Default::default(), LineEnding::None));
435 }
436 let mut lines_iter = lines.into_iter();
437
438 if let Some((range, ending)) = lines_iter.next() {
440 let data_line = &data[range];
441 let mut these_attrs = final_attrs.split_off(data_line.len());
442 remaining_split_len -= data_line.len() + ending.as_str().len();
443 core::mem::swap(&mut these_attrs, &mut final_attrs);
444 line.append(&BufferLine::new(
445 data_line,
446 ending,
447 these_attrs,
448 Shaping::Advanced,
449 ));
450 }
451 if let Some((range, ending)) = lines_iter.next_back() {
453 let data_line = &data[range];
454 remaining_split_len -= data_line.len() + ending.as_str().len();
455 let mut tmp = BufferLine::new(
456 data_line,
457 ending,
458 final_attrs.split_off(remaining_split_len),
459 Shaping::Advanced,
460 );
461 tmp.append(&after);
462 buffer.lines.insert(insert_line, tmp);
463 cursor.line += 1;
464 } else {
465 line.append(&after);
466 }
467 for (range, ending) in lines_iter.rev() {
469 let data_line = &data[range];
470 remaining_split_len -= data_line.len() + ending.as_str().len();
471 let tmp = BufferLine::new(
472 data_line,
473 ending,
474 final_attrs.split_off(remaining_split_len),
475 Shaping::Advanced,
476 );
477 buffer.lines.insert(insert_line, tmp);
478 cursor.line += 1;
479 }
480
481 assert_eq!(remaining_split_len, 0);
482
483 cursor.index = buffer.lines[cursor.line].text().len() - after_len;
485
486 ChangeItem {
487 start,
488 end: cursor,
489 text: data.to_string(),
490 insert: true,
491 }
492 });
493
494 if let Some(ref mut change) = self.change {
495 change.items.push(change_item);
496 }
497
498 cursor
499 }
500
501 fn copy_selection(&self) -> Option<String> {
502 let (start, end) = self.selection_bounds()?;
503 self.with_buffer(|buffer| {
504 let mut selection = String::new();
505 {
507 if start.line == end.line {
509 selection.push_str(&buffer.lines[start.line].text()[start.index..end.index]);
510 } else {
511 selection.push_str(&buffer.lines[start.line].text()[start.index..]);
512 selection.push('\n');
513 }
514 }
515
516 for line_i in start.line + 1..end.line {
518 selection.push_str(buffer.lines[line_i].text());
519 selection.push('\n');
520 }
521
522 if end.line > start.line {
524 selection.push_str(&buffer.lines[end.line].text()[..end.index]);
526 }
527
528 Some(selection)
529 })
530 }
531
532 fn delete_selection(&mut self) -> bool {
533 let Some((start, end)) = self.selection_bounds() else {
534 return false;
535 };
536
537 self.cursor = start;
539
540 self.selection = Selection::None;
542
543 self.delete_range(start, end);
545
546 true
547 }
548
549 fn apply_change(&mut self, change: &Change) -> bool {
550 if let Some(pending) = self.change.take() {
552 if !pending.items.is_empty() {
553 log::warn!("pending change caused apply_change to be ignored!");
555 self.change = Some(pending);
556 return false;
557 }
558 }
559
560 for item in &change.items {
561 if item.insert {
563 self.cursor = self.insert_at(item.start, &item.text, None);
564 } else {
565 self.cursor = item.start;
566 self.delete_range(item.start, item.end);
567 }
568 }
569 true
570 }
571
572 fn start_change(&mut self) {
573 if self.change.is_none() {
574 self.change = Some(Change::default());
575 }
576 }
577
578 fn finish_change(&mut self) -> Option<Change> {
579 self.change.take()
580 }
581
582 fn action(&mut self, font_system: &mut FontSystem, action: Action) {
583 let old_cursor = self.cursor;
584
585 match action {
586 Action::Motion(motion) => {
587 let cursor = self.cursor;
588 let cursor_x_opt = self.cursor_x_opt;
589 if let Some((new_cursor, new_cursor_x_opt)) = self.with_buffer_mut(|buffer| {
590 buffer.cursor_motion(font_system, cursor, cursor_x_opt, motion)
591 }) {
592 self.cursor = new_cursor;
593 self.cursor_x_opt = new_cursor_x_opt;
594 }
595 }
596 Action::Escape => {
597 match self.selection {
598 Selection::None => {}
599 _ => self.with_buffer_mut(|buffer| buffer.set_redraw(true)),
600 }
601 self.selection = Selection::None;
602 }
603 Action::Insert(character) => {
604 if character.is_control() && !['\t', '\n', '\u{92}'].contains(&character) {
605 log::debug!("Refusing to insert control character {character:?}");
607 } else if character == '\n' {
608 self.action(font_system, Action::Enter);
609 } else {
610 let mut str_buf = [0u8; 8];
611 let str_ref = character.encode_utf8(&mut str_buf);
612 self.insert_string(str_ref, None);
613 }
614 }
615 Action::Enter => {
616 if self.auto_indent {
618 let mut string = String::from("\n");
619 self.with_buffer(|buffer| {
620 let line = &buffer.lines[self.cursor.line];
621 let text = line.text();
622 for c in text.chars() {
623 if c.is_whitespace() {
624 string.push(c);
625 } else {
626 break;
627 }
628 }
629 });
630 self.insert_string(&string, None);
631 } else {
632 self.insert_string("\n", None);
633 }
634
635 let line_i = self.cursor.line;
637 self.with_buffer_mut(|buffer| {
638 buffer.line_layout(font_system, line_i);
639 });
640 }
641 Action::Backspace => {
642 if self.delete_selection() {
643 } else {
645 let end = self.cursor;
647
648 if self.cursor.index > 0 {
649 self.cursor.index = self.with_buffer(|buffer| {
651 buffer.lines[self.cursor.line].text()[..self.cursor.index]
652 .char_indices()
653 .next_back()
654 .map_or(0, |(i, _)| i)
655 });
656 } else if self.cursor.line > 0 {
657 self.cursor.line -= 1;
659 self.cursor.index =
660 self.with_buffer(|buffer| buffer.lines[self.cursor.line].text().len());
661 }
662
663 if self.cursor != end {
664 self.delete_range(self.cursor, end);
666 }
667 }
668 }
669 Action::Delete => {
670 if self.delete_selection() {
671 } else {
673 let mut start = self.cursor;
675 let mut end = self.cursor;
676
677 self.with_buffer(|buffer| {
678 if start.index < buffer.lines[start.line].text().len() {
679 let line = &buffer.lines[start.line];
680
681 let range_opt = line
682 .text()
683 .grapheme_indices(true)
684 .take_while(|(i, _)| *i <= start.index)
685 .last()
686 .map(|(i, c)| i..(i + c.len()));
687
688 if let Some(range) = range_opt {
689 start.index = range.start;
690 end.index = range.end;
691 }
692 } else if start.line + 1 < buffer.lines.len() {
693 end.line += 1;
694 end.index = 0;
695 }
696 });
697
698 if start != end {
699 self.cursor = start;
700 self.delete_range(start, end);
701 }
702 }
703 }
704 Action::Indent => {
705 let (start, end) = match self.selection_bounds() {
707 Some(some) => some,
708 None => (self.cursor, self.cursor),
709 };
710
711 let tab_width: usize = self.tab_width().into();
713 for line_i in start.line..=end.line {
714 let mut after_whitespace = 0;
716 let mut required_indent = 0;
717 self.with_buffer(|buffer| {
718 let line = &buffer.lines[line_i];
719 let text = line.text();
720
721 if self.selection == Selection::None {
722 let whitespace_length = match line.text()[0..self.cursor.index]
724 .chars()
725 .rev()
726 .position(|c| !c.is_whitespace())
727 {
728 Some(length) => length,
729 None => self.cursor.index,
731 };
732 required_indent = tab_width - (whitespace_length % tab_width);
733 after_whitespace = self.cursor.index;
734 } else {
735 for (count, (index, c)) in text.char_indices().enumerate() {
737 if !c.is_whitespace() {
738 after_whitespace = index;
739 required_indent = tab_width - (count % tab_width);
740 break;
741 }
742 }
743 }
744 });
745
746 self.insert_at(
747 Cursor::new(line_i, after_whitespace),
748 &" ".repeat(required_indent),
749 None,
750 );
751
752 if self.cursor.line == line_i {
754 if self.cursor.index < after_whitespace {
756 self.cursor.index = after_whitespace;
757 }
758 self.cursor.index += required_indent;
759 }
760
761 match self.selection {
763 Selection::None => {}
764 Selection::Normal(ref mut select)
765 | Selection::Line(ref mut select)
766 | Selection::Word(ref mut select) => {
767 if select.line == line_i && select.index >= after_whitespace {
768 select.index += required_indent;
769 }
770 }
771 }
772 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
774 }
775 }
776 Action::Unindent => {
777 let (start, end) = match self.selection_bounds() {
779 Some(some) => some,
780 None => (self.cursor, self.cursor),
781 };
782
783 let tab_width: usize = self.tab_width().into();
785 for line_i in start.line..=end.line {
786 let mut last_indent = 0;
788 let mut after_whitespace = 0;
789 self.with_buffer(|buffer| {
790 let line = &buffer.lines[line_i];
791 let text = line.text();
792 after_whitespace = text.len();
794 for (count, (index, c)) in text.char_indices().enumerate() {
795 if !c.is_whitespace() {
796 after_whitespace = index;
797 break;
798 }
799 if count % tab_width == 0 {
800 last_indent = index;
801 }
802 }
803 });
804
805 if last_indent == after_whitespace {
807 continue;
808 }
809
810 self.delete_range(
812 Cursor::new(line_i, last_indent),
813 Cursor::new(line_i, after_whitespace),
814 );
815
816 if self.cursor.line == line_i && self.cursor.index > last_indent {
818 self.cursor.index -= after_whitespace - last_indent;
819 }
820
821 match self.selection {
823 Selection::None => {}
824 Selection::Normal(ref mut select)
825 | Selection::Line(ref mut select)
826 | Selection::Word(ref mut select) => {
827 if select.line == line_i && select.index > last_indent {
828 select.index -= after_whitespace - last_indent;
829 }
830 }
831 }
832
833 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
835 }
836 }
837 Action::Click { x, y } => {
838 self.set_selection(Selection::None);
839
840 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
841 {
842 if new_cursor != self.cursor {
843 self.cursor = new_cursor;
844 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
845 }
846 }
847 }
848 Action::DoubleClick { x, y } => {
849 self.set_selection(Selection::None);
850
851 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
852 {
853 if new_cursor != self.cursor {
854 self.cursor = new_cursor;
855 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
856 }
857 self.selection = Selection::Word(self.cursor);
858 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
859 }
860 }
861 Action::TripleClick { x, y } => {
862 self.set_selection(Selection::None);
863
864 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
865 {
866 if new_cursor != self.cursor {
867 self.cursor = new_cursor;
868 }
869 self.selection = Selection::Line(self.cursor);
870 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
871 }
872 }
873 Action::Drag { x, y } => {
874 if self.selection == Selection::None {
875 self.selection = Selection::Normal(self.cursor);
876 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
877 }
878
879 if let Some(new_cursor) = self.with_buffer(|buffer| buffer.hit(x as f32, y as f32))
880 {
881 if new_cursor != self.cursor {
882 self.cursor = new_cursor;
883 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
884 }
885 }
886 }
887 Action::Scroll { pixels } => {
888 self.with_buffer_mut(|buffer| {
889 let mut scroll = buffer.scroll();
890 scroll.vertical += pixels;
892 buffer.set_scroll(scroll);
893 });
894 }
895 }
896
897 if old_cursor != self.cursor {
898 self.cursor_moved = true;
899 self.with_buffer_mut(|buffer| buffer.set_redraw(true));
900
901 }
917 }
918
919 fn cursor_position(&self) -> Option<(i32, i32)> {
920 self.with_buffer(|buffer| {
921 buffer
922 .layout_runs()
923 .find_map(|run| cursor_position(&self.cursor, &run))
924 })
925 }
926}
927
928impl BorrowedWithFontSystem<'_, Editor<'_>> {
929 #[cfg(feature = "swash")]
930 pub fn draw<F>(
931 &mut self,
932 cache: &mut crate::SwashCache,
933 text_color: Color,
934 cursor_color: Color,
935 selection_color: Color,
936 selected_text_color: Color,
937 f: F,
938 ) where
939 F: FnMut(i32, i32, u32, u32, Color),
940 {
941 self.inner.draw(
942 self.font_system,
943 cache,
944 text_color,
945 cursor_color,
946 selection_color,
947 selected_text_color,
948 f,
949 );
950 }
951}