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