1use crate::clipboard::{global_clipboard, Clipboard};
2use crate::core::{TextCore, TextString};
3use crate::grapheme::GlyphIter;
4use crate::text_mask_core::mask::{EditDirection, Mask, MaskToken};
5use crate::undo_buffer::{UndoBuffer, UndoEntry, UndoVec};
6use crate::{upos_type, Cursor, Glyph, Grapheme, TextError, TextPosition, TextRange};
7use format_num_pattern::core::{clean_num, map_num};
8use format_num_pattern::{CurrencySym, NumberFormat, NumberSymbols};
9use std::borrow::Cow;
10use std::fmt;
11use std::iter::once;
12use std::ops::Range;
13use unicode_segmentation::UnicodeSegmentation;
14
15#[derive(Debug, Clone)]
17pub struct MaskedCore {
18 masked: TextCore<TextString>,
20 sym: Option<NumberSymbols>,
22 mask: Vec<MaskToken>,
24}
25
26impl Default for MaskedCore {
27 fn default() -> Self {
28 let mut value = TextCore::new(
29 Some(Box::new(UndoVec::new(99))),
30 Some(Box::new(global_clipboard())),
31 );
32 value.set_glyph_line_break(false);
33
34 Self {
35 masked: value,
36 sym: None,
37 mask: Default::default(),
38 }
39 }
40}
41
42impl MaskedCore {
43 pub fn new() -> Self {
44 Self::default()
45 }
46
47 pub fn set_num_symbols(&mut self, sym: NumberSymbols) {
51 self.sym = Some(sym);
52 }
53
54 fn dec_sep(&self) -> char {
55 if let Some(sym) = &self.sym {
56 sym.decimal_sep
57 } else {
58 '.'
59 }
60 }
61
62 fn grp_sep(&self) -> char {
63 if let Some(sym) = &self.sym {
64 sym.decimal_grp.unwrap_or(' ')
68 } else {
69 ','
70 }
71 }
72
73 fn neg_sym(&self) -> char {
74 if let Some(sym) = &self.sym {
75 sym.negative_sym
76 } else {
77 '-'
78 }
79 }
80
81 fn pos_sym(&self) -> char {
82 if let Some(sym) = &self.sym {
83 sym.positive_sym
84 } else {
85 ' '
86 }
87 }
88
89 pub fn set_mask<S: AsRef<str>>(&mut self, s: S) -> Result<(), fmt::Error> {
92 self.mask = Self::parse_mask(s.as_ref())?;
93 self.clear();
94 Ok(())
95 }
96
97 #[allow(clippy::needless_range_loop)]
98 fn parse_mask(mask_str: &str) -> Result<Vec<MaskToken>, fmt::Error> {
99 let mut out = Vec::<MaskToken>::new();
100
101 let mut start_sub = 0;
102 let mut start_sec = 0;
103 let mut sec_id = 0;
104 let mut last_mask = Mask::None;
105 let mut dec_dir = EditDirection::Rtol;
106 let mut esc = false;
107 let mut idx = 0;
108 for m in mask_str.graphemes(true).chain(once("")) {
109 let mask = if esc {
110 esc = false;
111 Mask::Separator(Box::from(m))
112 } else {
113 match m {
114 "0" => Mask::Digit0(dec_dir),
115 "9" => Mask::Digit(dec_dir),
116 "#" => Mask::Numeric(dec_dir),
117 "." => Mask::DecimalSep,
118 "," => Mask::GroupingSep,
119 "-" => Mask::Sign,
120 "+" => Mask::Plus,
121 "h" => Mask::Hex,
122 "H" => Mask::Hex0,
123 "o" => Mask::Oct,
124 "O" => Mask::Oct0,
125 "d" => Mask::Dec,
126 "D" => Mask::Dec0,
127 "l" => Mask::Letter,
128 "a" => Mask::LetterOrDigit,
129 "c" => Mask::LetterDigitSpace,
130 "_" => Mask::AnyChar,
131 "" => Mask::None,
132 " " => Mask::Separator(Box::from(m)),
133 "\\" => {
134 esc = true;
135 continue;
136 }
137 _ => return Err(fmt::Error),
138 }
139 };
140
141 match mask {
142 Mask::Digit0(_)
143 | Mask::Digit(_)
144 | Mask::Numeric(_)
145 | Mask::GroupingSep
146 | Mask::Sign
147 | Mask::Plus => {
148 }
150 Mask::DecimalSep => {
151 dec_dir = EditDirection::Ltor;
152 }
153 Mask::Hex0
154 | Mask::Hex
155 | Mask::Oct0
156 | Mask::Oct
157 | Mask::Dec0
158 | Mask::Dec
159 | Mask::Letter
160 | Mask::LetterOrDigit
161 | Mask::LetterDigitSpace
162 | Mask::AnyChar
163 | Mask::Separator(_) => {
164 dec_dir = EditDirection::Rtol
166 }
167 Mask::None => {
168 }
170 }
171
172 if matches!(mask, Mask::Separator(_)) || mask.section() != last_mask.section() {
173 for j in start_sec..idx {
174 out[j].sec_id = sec_id;
175 out[j].sec_start = start_sec as upos_type;
176 out[j].sec_end = idx as upos_type;
177 }
178 sec_id += 1;
179 start_sec = idx;
180 }
181 if matches!(mask, Mask::Separator(_)) || mask.sub_section() != last_mask.sub_section() {
182 for j in start_sub..idx {
183 out[j].sub_start = start_sub as upos_type;
184 out[j].sub_end = idx as upos_type;
185 }
186 start_sub = idx;
187 }
188
189 let tok = MaskToken {
190 sec_id: 0,
191 sec_start: 0,
192 sec_end: 0,
193 sub_start: 0,
194 sub_end: 0,
195 peek_left: last_mask,
196 right: mask.clone(),
197 edit: mask.edit_value().into(),
198 };
199 out.push(tok);
200
201 idx += 1;
202 last_mask = mask;
203 }
204 for j in start_sec..out.len() {
205 out[j].sec_id = sec_id;
206 out[j].sec_start = start_sec as upos_type;
207 out[j].sec_end = mask_str.graphemes(true).count() as upos_type;
208 }
209 for j in start_sub..out.len() {
210 out[j].sub_start = start_sub as upos_type;
211 out[j].sub_end = mask_str.graphemes(true).count() as upos_type;
212 }
213
214 Ok(out)
215 }
216
217 pub fn mask(&self) -> String {
219 use std::fmt::Write;
220
221 let mut buf = String::new();
222 for t in self.mask.iter() {
223 _ = write!(buf, "{}", t.right);
224 }
225 buf
226 }
227}
228
229impl MaskedCore {
230 pub fn set_clipboard(&mut self, clip: Option<Box<dyn Clipboard + 'static>>) {
232 self.masked.set_clipboard(clip);
233 }
234
235 pub fn clipboard(&self) -> Option<&dyn Clipboard> {
237 self.masked.clipboard()
238 }
239}
240
241impl MaskedCore {
242 #[inline]
244 pub fn set_undo_buffer(&mut self, undo: Option<Box<dyn UndoBuffer>>) {
245 self.masked.set_undo_buffer(undo);
246 }
247
248 #[inline]
250 pub fn set_undo_count(&mut self, n: u32) {
251 self.masked.set_undo_count(n);
252 }
253
254 #[inline]
256 pub fn begin_undo_seq(&mut self) {
257 self.masked.begin_undo_seq();
258 }
259
260 #[inline]
262 pub fn end_undo_seq(&mut self) {
263 self.masked.end_undo_seq();
264 }
265
266 #[inline]
268 pub fn undo_buffer(&self) -> Option<&dyn UndoBuffer> {
269 self.masked.undo_buffer()
270 }
271
272 #[inline]
274 pub fn undo_buffer_mut(&mut self) -> Option<&mut dyn UndoBuffer> {
275 self.masked.undo_buffer_mut()
276 }
277
278 pub fn undo(&mut self) -> bool {
280 self.masked.undo()
281 }
282
283 pub fn redo(&mut self) -> bool {
285 self.masked.redo()
286 }
287
288 pub fn recent_replay_log(&mut self) -> Vec<UndoEntry> {
290 self.masked.recent_replay_log()
291 }
292
293 pub fn replay_log(&mut self, replay: &[UndoEntry]) {
295 self.masked.replay_log(replay)
296 }
297}
298
299impl MaskedCore {
300 #[inline]
305 pub fn set_styles(&mut self, new_styles: Vec<(Range<usize>, usize)>) {
306 self.masked.set_styles(new_styles);
307 }
308
309 #[inline]
314 pub fn add_style(&mut self, range: Range<usize>, style: usize) {
315 self.masked.add_style(range, style);
316 }
317
318 #[inline]
322 pub fn remove_style(&mut self, range: Range<usize>, style: usize) {
323 self.masked.remove_style(range, style);
324 }
325
326 #[inline]
330 pub(crate) fn styles_at_page(&self, range: Range<usize>, pos: usize, buf: &mut Vec<usize>) {
331 self.masked.styles_at_page(range, pos, buf);
332 }
333
334 pub fn styles_in(&self, range: Range<usize>, buf: &mut Vec<(Range<usize>, usize)>) {
336 self.masked.styles_in(range, buf)
337 }
338
339 #[inline]
341 pub fn styles_at(&self, byte_pos: usize, buf: &mut Vec<(Range<usize>, usize)>) {
342 self.masked.styles_at(byte_pos, buf);
343 }
344
345 #[inline]
348 pub fn style_match(&self, byte_pos: usize, style: usize) -> Option<Range<usize>> {
349 self.masked.style_match(byte_pos, style)
350 }
351
352 #[inline]
354 pub fn styles(&self) -> Option<impl Iterator<Item = (Range<usize>, usize)> + '_> {
355 self.masked.styles()
356 }
357}
358
359impl MaskedCore {
360 pub fn set_cursor(&mut self, cursor: upos_type, extend_selection: bool) -> bool {
366 self.masked
367 .set_cursor(TextPosition::new(cursor, 0), extend_selection)
368 }
369
370 fn number_cursor(&self, range: Range<upos_type>) -> upos_type {
372 for (i, t) in self.mask[range.start as usize..range.end as usize]
373 .iter()
374 .enumerate()
375 .rev()
376 {
377 match t.right {
378 Mask::Digit(EditDirection::Rtol)
379 | Mask::Digit0(EditDirection::Rtol)
380 | Mask::Numeric(EditDirection::Rtol) => {
381 return range.start + i as upos_type + 1;
382 }
383 _ => {}
384 }
385 }
386 range.start
387 }
388
389 pub fn section_cursor(&self, cursor: upos_type) -> Option<upos_type> {
392 if cursor as usize >= self.mask.len() {
393 return None;
394 }
395
396 let mask = &self.mask[cursor as usize];
397
398 if mask.right.is_number() {
399 Some(self.number_cursor(mask.sec_start..mask.sec_end))
400 } else if mask.right.is_separator() {
401 None
402 } else if mask.right.is_none() {
403 None
404 } else {
405 Some(mask.sec_start)
406 }
407 }
408
409 pub fn next_section_cursor(&self, cursor: upos_type) -> Option<upos_type> {
411 if cursor as usize >= self.mask.len() {
412 return None;
413 }
414
415 let mut mask = &self.mask[cursor as usize];
416 let mut next;
417 loop {
418 if mask.right.is_none() {
419 return None;
420 }
421
422 next = mask.sec_end;
423 mask = &self.mask[next as usize];
424
425 if mask.right.is_number() {
426 return Some(self.number_cursor(mask.sec_start..mask.sec_end));
427 } else if mask.right.is_separator() {
428 continue;
429 } else if mask.right.is_none() {
430 return None;
431 } else {
432 return Some(mask.sec_start);
433 }
434 }
435 }
436
437 pub fn prev_section_cursor(&self, cursor: upos_type) -> Option<upos_type> {
439 if cursor as usize >= self.mask.len() {
440 return None;
441 }
442
443 let mut prev = self.mask[cursor as usize].sec_start;
444 let mut mask = &self.mask[prev as usize];
445
446 loop {
447 if mask.peek_left.is_none() {
448 return None;
449 }
450
451 prev = self.mask[mask.sec_start as usize - 1].sec_start;
452 mask = &self.mask[prev as usize];
453
454 if mask.right.is_number() {
455 return Some(self.number_cursor(mask.sec_start..mask.sec_end));
456 } else if mask.right.is_separator() {
457 continue;
458 } else {
459 return Some(mask.sec_start);
460 }
461 }
462 }
463
464 pub fn is_section_boundary(&self, pos: upos_type) -> bool {
466 if pos == 0 {
467 return false;
468 }
469 if pos as usize >= self.mask.len() {
470 return false;
471 }
472 let prev = &self.mask[pos as usize - 1];
473 let mask = &self.mask[pos as usize];
474 prev.sec_id != mask.sec_id
475 }
476
477 pub fn section_range(&self, cursor: upos_type) -> Option<Range<upos_type>> {
480 if cursor as usize >= self.mask.len() {
481 return None;
482 }
483
484 let mask = &self.mask[cursor as usize];
485 if mask.right.is_number() {
486 Some(mask.sec_start..mask.sec_end)
487 } else if mask.right.is_separator() {
488 None
489 } else if mask.right.is_none() {
490 None
491 } else {
492 Some(mask.sec_start..mask.sec_end)
493 }
494 }
495
496 pub fn next_section_range(&self, cursor: upos_type) -> Option<Range<upos_type>> {
498 if cursor as usize >= self.mask.len() {
499 return None;
500 }
501
502 let mut mask = &self.mask[cursor as usize];
503 let mut next;
504 loop {
505 if mask.right.is_none() {
506 return None;
507 }
508
509 next = mask.sec_end;
510 mask = &self.mask[next as usize];
511
512 if mask.right.is_number() {
513 return Some(mask.sec_start..mask.sec_end);
514 } else if mask.right.is_separator() {
515 continue;
516 } else if mask.right.is_none() {
517 return None;
518 } else {
519 return Some(mask.sec_start..mask.sec_end);
520 }
521 }
522 }
523
524 pub fn prev_section_range(&self, cursor: upos_type) -> Option<Range<upos_type>> {
526 if cursor as usize >= self.mask.len() {
527 return None;
528 }
529
530 let mut prev = self.mask[cursor as usize].sec_start;
531 let mut mask = &self.mask[prev as usize];
532 loop {
533 if mask.peek_left.is_none() {
534 return None;
535 }
536
537 prev = self.mask[mask.sec_start as usize - 1].sec_start;
538 mask = &self.mask[prev as usize];
539
540 if mask.right.is_number() {
541 return Some(mask.sec_start..mask.sec_end);
542 } else if mask.right.is_separator() {
543 continue;
544 } else {
545 return Some(mask.sec_start..mask.sec_end);
546 }
547 }
548 }
549
550 #[inline]
553 pub fn set_default_cursor(&mut self) {
554 if let Some(pos) = self.section_cursor(0) {
555 self.masked.set_cursor(TextPosition::new(pos, 0), false);
556 } else if let Some(pos) = self.next_section_cursor(0) {
557 self.masked.set_cursor(TextPosition::new(pos, 0), false);
558 } else {
559 self.masked.set_cursor(TextPosition::new(0, 0), false);
560 }
561 }
562
563 #[inline]
565 pub fn cursor(&self) -> upos_type {
566 self.masked.cursor().x
567 }
568
569 #[inline]
571 pub fn anchor(&self) -> upos_type {
572 self.masked.anchor().x
573 }
574
575 #[inline]
577 pub fn has_selection(&self) -> bool {
578 self.masked.has_selection()
579 }
580
581 #[inline]
583 pub fn set_selection(&mut self, anchor: upos_type, cursor: upos_type) -> bool {
584 self.masked
585 .set_selection(TextPosition::new(anchor, 0), TextPosition::new(cursor, 0))
586 }
587
588 #[inline]
590 pub fn select_all(&mut self) -> bool {
591 self.masked.select_all()
592 }
593
594 #[inline]
596 pub fn selection(&self) -> Range<upos_type> {
597 let selection = self.masked.selection();
598 selection.start.x..selection.end.x
599 }
600
601 #[inline]
603 pub fn selected_text(&self) -> &str {
604 match self
605 .masked
606 .str_slice(self.masked.selection())
607 .expect("valid_range")
608 {
609 Cow::Borrowed(v) => v,
610 Cow::Owned(_) => {
611 unreachable!()
612 }
613 }
614 }
615}
616
617impl MaskedCore {
618 #[inline]
620 pub fn is_empty(&self) -> bool {
621 self.masked.text().as_str() == self.default_value()
622 }
623
624 #[inline]
627 pub fn byte_at(&self, pos: upos_type) -> Result<Range<usize>, TextError> {
628 self.masked.byte_at(TextPosition::new(pos, 0))
629 }
630
631 #[inline]
633 pub fn bytes_at_range(&self, range: Range<upos_type>) -> Result<Range<usize>, TextError> {
634 self.masked
635 .bytes_at_range(TextRange::new((range.start, 0), (range.end, 0)))
636 }
637
638 #[inline]
641 pub fn byte_pos(&self, byte: usize) -> Result<upos_type, TextError> {
642 Ok(self.masked.byte_pos(byte)?.x)
643 }
644
645 #[inline]
647 pub fn byte_range(&self, bytes: Range<usize>) -> Result<Range<upos_type>, TextError> {
648 let r = self.masked.byte_range(bytes)?;
649 Ok(r.start.x..r.end.x)
650 }
651
652 #[inline]
654 pub fn str_slice_byte(&self, range: Range<usize>) -> Result<Cow<'_, str>, TextError> {
655 self.masked.str_slice_byte(range)
656 }
657
658 #[inline]
660 pub fn str_slice(&self, range: Range<upos_type>) -> Result<Cow<'_, str>, TextError> {
661 self.masked
662 .str_slice(TextRange::new((range.start, 0), (range.end, 0)))
663 }
664
665 #[inline]
668 pub fn glyphs(
669 &self,
670 rows: Range<upos_type>,
671 screen_offset: u16,
672 screen_width: u16,
673 ) -> Result<impl Iterator<Item = Glyph<'_>>, TextError> {
674 let grapheme_iter = self.masked.graphemes(
675 TextRange::new((0, rows.start), (0, rows.end)),
676 TextPosition::new(0, rows.start),
677 )?;
678
679 let mask_iter = self.mask.iter();
680
681 let sym_neg = || self.neg_sym().to_string();
682 let sym_dec = || self.dec_sep().to_string();
683 let sym_grp = || self.grp_sep().to_string();
684 let sym_pos = || self.pos_sym().to_string();
685
686 let iter = grapheme_iter
687 .zip(mask_iter)
688 .map(move |(g, t)| match (&t.right, g.grapheme()) {
689 (Mask::Numeric(_), "-") => Grapheme::new(Cow::Owned(sym_neg()), g.text_bytes()),
690 (Mask::DecimalSep, ".") => Grapheme::new(Cow::Owned(sym_dec()), g.text_bytes()),
691 (Mask::GroupingSep, ",") => Grapheme::new(Cow::Owned(sym_grp()), g.text_bytes()),
692 (Mask::GroupingSep, "-") => Grapheme::new(Cow::Owned(sym_neg()), g.text_bytes()),
693 (Mask::Sign, "-") => Grapheme::new(Cow::Owned(sym_neg()), g.text_bytes()),
694 (Mask::Sign, _) => Grapheme::new(Cow::Owned(sym_pos()), g.text_bytes()),
695 (_, _) => g,
696 });
697
698 let mut it = GlyphIter::new(TextPosition::new(0, rows.start), iter);
699 it.set_screen_offset(screen_offset);
700 it.set_screen_width(screen_width);
701 it.set_tabs(self.masked.tab_width());
702 it.set_show_ctrl(self.masked.glyph_ctrl());
703 it.set_line_break(self.masked.glyph_line_break());
704 Ok(it)
705 }
706
707 #[inline]
712 pub fn condensed_glyphs(
713 &self,
714 rows: Range<upos_type>,
715 screen_offset: u16,
716 screen_width: u16,
717 ) -> Result<impl Iterator<Item = Glyph<'_>>, TextError> {
718 let grapheme_iter = self.masked.graphemes(
719 TextRange::new((0, rows.start), (0, rows.end)),
720 TextPosition::new(0, rows.start),
721 )?;
722
723 let mask_iter = self.mask.iter();
724
725 let sym_neg = || self.neg_sym().to_string();
726 let sym_dec = || self.dec_sep().to_string();
727 let sym_grp = || self.grp_sep().to_string();
728 let sym_pos = || self.pos_sym().to_string();
729
730 let iter =
731 grapheme_iter
732 .zip(mask_iter)
733 .filter_map(move |(g, t)| match (&t.right, g.grapheme()) {
734 (Mask::Numeric(_), "-") => {
735 Some(Grapheme::new(Cow::Owned(sym_neg()), g.text_bytes()))
736 }
737 (Mask::DecimalSep, ".") => {
738 Some(Grapheme::new(Cow::Owned(sym_dec()), g.text_bytes()))
739 }
740 (Mask::GroupingSep, ",") => {
741 Some(Grapheme::new(Cow::Owned(sym_grp()), g.text_bytes()))
742 }
743 (Mask::GroupingSep, "-") => {
744 Some(Grapheme::new(Cow::Owned(sym_neg()), g.text_bytes()))
745 }
746 (Mask::Sign, "-") => Some(Grapheme::new(Cow::Owned(sym_neg()), g.text_bytes())),
747
748 (Mask::Numeric(_), " ") => None,
749 (Mask::Digit(_), " ") => None,
750 (Mask::DecimalSep, " ") => None,
751 (Mask::GroupingSep, " ") => None,
752 (Mask::Sign, _) => {
753 if self.pos_sym() != ' ' {
754 Some(Grapheme::new(Cow::Owned(sym_pos()), g.text_bytes()))
755 } else {
756 None
757 }
758 }
759 (Mask::Hex, " ") => None,
760 (Mask::Oct, " ") => None,
761 (Mask::Dec, " ") => None,
762
763 (_, _) => Some(g),
764 });
765
766 let mut it = GlyphIter::new(TextPosition::new(0, rows.start), iter);
767 it.set_screen_offset(screen_offset);
768 it.set_screen_width(screen_width);
769 it.set_tabs(self.masked.tab_width());
770 it.set_show_ctrl(self.masked.glyph_ctrl());
771 it.set_line_break(self.masked.glyph_line_break());
772 Ok(it)
773 }
774
775 #[inline]
777 pub fn grapheme_at(&self, pos: upos_type) -> Result<Option<Grapheme<'_>>, TextError> {
778 self.masked.grapheme_at(TextPosition::new(pos, 0))
779 }
780
781 #[inline]
783 pub fn text_graphemes(
784 &self,
785 pos: upos_type,
786 ) -> Result<impl Cursor<Item = Grapheme<'_>>, TextError> {
787 self.masked.text_graphemes(TextPosition::new(pos, 0))
788 }
789
790 #[inline]
792 pub fn graphemes(
793 &self,
794 range: Range<upos_type>,
795 pos: upos_type,
796 ) -> Result<impl Cursor<Item = Grapheme<'_>>, TextError> {
797 self.masked.graphemes(
798 TextRange::new((range.start, 0), (range.end, 0)),
799 TextPosition::new(pos, 0),
800 )
801 }
802
803 #[inline]
804 pub fn line_width(&self) -> upos_type {
805 self.masked.line_width(0).expect("valid_row")
806 }
807}
808
809impl MaskedCore {
810 #[inline]
812 fn default_value(&self) -> String {
813 MaskToken::empty_section(&self.mask)
814 }
815}
816
817impl MaskedCore {
818 #[inline]
821 pub fn clear(&mut self) {
822 self.masked
823 .set_text(TextString::new_string(self.default_value()));
824 self.set_default_cursor();
825 }
826
827 pub fn text(&self) -> &str {
829 self.masked.text().as_str()
830 }
831
832 #[allow(clippy::comparison_chain)]
837 pub fn set_text<S: Into<String>>(&mut self, s: S) {
838 let mut text = s.into();
839 while text.graphemes(true).count() > self.mask.len().saturating_sub(1) {
840 text.pop();
841 }
842 while text.graphemes(true).count() < self.mask.len().saturating_sub(1) {
843 text.push(' ');
844 }
845 let len = text.graphemes(true).count();
846
847 assert_eq!(len, self.mask.len().saturating_sub(1));
848
849 self.masked.set_text(TextString::new_string(text));
850 }
851
852 #[allow(clippy::if_same_then_else)]
855 pub fn advance_cursor(&mut self, c: char) -> bool {
856 if self.mask.is_empty() {
857 return false;
858 }
859
860 let mask_c = &self.mask[self.masked.cursor().x as usize];
861
862 let mut new_cursor = self.masked.cursor().x;
863
864 loop {
865 let mask = &self.mask[new_cursor as usize];
866
867 if self.can_insert_integer_left(mask, new_cursor, c) {
868 break;
871 } else if self.can_insert_integer(mask, new_cursor, c) {
872 break;
875 } else if self.can_insert_sign(mask, new_cursor, c) {
876 break;
878 } else if self.can_insert_decimal_sep(mask, c) {
879 break;
881 } else if mask.right == Mask::GroupingSep {
882 new_cursor += 1;
884 } else if self.can_insert_separator(mask, c) {
885 break;
886 } else if self.can_move_left_in_fraction(mask_c, mask, new_cursor, c) {
887 new_cursor -= 1;
889 } else if self.can_insert_fraction(mask_c, mask, c) {
890 break;
891 } else if self.can_insert_other(mask, c) {
892 break;
893 } else if mask.right == Mask::None {
894 new_cursor = self.masked.cursor().x;
896 break;
897 } else {
898 new_cursor += 1;
899 }
900 }
901
902 self.masked
903 .set_cursor(TextPosition::new(new_cursor, 0), false)
904 }
905
906 fn is_valid_char(&self, mask: &Mask, c: char) -> bool {
908 match mask {
909 Mask::Digit0(_) => c.is_ascii_digit(),
910 Mask::Digit(_) => c.is_ascii_digit() || c == ' ',
911 Mask::Numeric(_) => c.is_ascii_digit() || c == self.neg_sym() || c == '-',
912 Mask::DecimalSep => c == self.dec_sep(),
913 Mask::GroupingSep => false,
914 Mask::Sign => c == self.neg_sym() || c == '-',
915 Mask::Plus => c == self.neg_sym() || c == '-',
916 Mask::Hex0 => c.is_ascii_hexdigit(),
917 Mask::Hex => c.is_ascii_hexdigit() || c == ' ',
918 Mask::Oct0 => c.is_digit(8),
919 Mask::Oct => c.is_digit(8) || c == ' ',
920 Mask::Dec0 => c.is_ascii_digit(),
921 Mask::Dec => c.is_ascii_digit() || c == ' ',
922 Mask::Letter => c.is_alphabetic(),
923 Mask::LetterOrDigit => c.is_alphanumeric(),
924 Mask::LetterDigitSpace => c.is_alphanumeric() || c == ' ',
925 Mask::AnyChar => true,
926 Mask::Separator(sep) => {
927 if c == '.' || c == ',' {
929 true
930 } else if let Some(sepc) = sep.chars().next() {
931 sepc == c
933 } else {
934 false
935 }
936 }
937 Mask::None => false,
938 }
939 }
940
941 #[inline]
943 fn can_insert_other(&self, mask: &MaskToken, c: char) -> bool {
944 match mask.right {
945 Mask::Hex0
946 | Mask::Hex
947 | Mask::Oct0
948 | Mask::Oct
949 | Mask::Dec0
950 | Mask::Dec
951 | Mask::Letter
952 | Mask::LetterOrDigit
953 | Mask::LetterDigitSpace
954 | Mask::AnyChar => self.is_valid_char(&mask.right, c),
955 _ => false,
956 }
957 }
958
959 #[inline]
961 fn can_insert_fraction(&self, mask_c: &MaskToken, mask: &MaskToken, c: char) -> bool {
962 if !mask.right.is_fraction() {
963 return false;
964 }
965 if !self.is_valid_char(&mask.right, c) {
966 return false;
967 }
968 if mask_c.is_integer_part() {
970 return false;
971 }
972
973 true
974 }
975
976 #[inline]
980 fn can_move_left_in_fraction(
981 &self,
982 mask_c: &MaskToken,
983 mask: &MaskToken,
984 new_cursor: upos_type,
985 c: char,
986 ) -> bool {
987 if !mask.peek_left.is_fraction() {
988 return false;
989 }
990 if !self.is_valid_char(&mask.peek_left, c) {
991 return false;
992 }
993 if mask_c.is_integer_part() {
995 return false;
996 }
997
998 let gl = self
999 .masked
1000 .grapheme_at(TextPosition::new(new_cursor - 1, 0))
1001 .expect("valid_position")
1002 .expect("grapheme");
1003
1004 if gl != " " {
1006 return false;
1007 }
1008
1009 true
1010 }
1011
1012 #[inline]
1014 fn can_insert_sign<'a>(
1015 &'a self,
1016 mut mask: &'a MaskToken,
1017 new_cursor: upos_type,
1018 c: char,
1019 ) -> bool {
1020 if !self.is_valid_char(&Mask::Sign, c) {
1021 return false;
1022 }
1023 if mask.peek_left.is_number() && (mask.right.is_ltor() || mask.right.is_none()) {
1025 mask = &self.mask[new_cursor as usize - 1];
1026 }
1027 if !mask.right.is_number() {
1028 return false;
1029 }
1030
1031 for i in mask.sec_start..mask.sec_end {
1033 let t = &self.mask[i as usize];
1034 match t.right {
1035 Mask::Plus => return true,
1036 Mask::Sign => return true,
1037 Mask::Numeric(EditDirection::Rtol) => {
1038 let gi = self
1041 .masked
1042 .grapheme_at(TextPosition::new(i, 0))
1043 .expect("valid_position")
1044 .expect("grapheme");
1045
1046 return t.right.can_drop(gi.grapheme()) || gi == "-";
1047 }
1048 _ => {}
1049 }
1050 }
1051
1052 false
1053 }
1054
1055 #[inline]
1057 fn can_insert_integer(&self, mask: &MaskToken, new_cursor: upos_type, c: char) -> bool {
1058 if !mask.right.is_rtol() {
1059 return false;
1060 }
1061
1062 if !self.is_valid_char(&mask.right, c) {
1063 return false;
1064 }
1065
1066 let g = self
1067 .masked
1068 .grapheme_at(TextPosition::new(new_cursor, 0))
1069 .expect("valid_position")
1070 .expect("grapheme");
1071 if mask.right.can_drop(g.grapheme()) {
1072 return false;
1073 }
1074 if g == "-" {
1075 return false;
1076 }
1077
1078 true
1079 }
1080
1081 #[inline]
1083 fn can_insert_separator(&self, mask: &MaskToken, c: char) -> bool {
1084 if !matches!(mask.right, Mask::Separator(_)) {
1085 return false;
1086 }
1087 if !self.is_valid_char(&mask.right, c) {
1088 return false;
1089 }
1090 true
1091 }
1092
1093 #[inline]
1095 fn can_insert_decimal_sep(&self, mask: &MaskToken, c: char) -> bool {
1096 if mask.right != Mask::DecimalSep {
1097 return false;
1098 }
1099 if !self.is_valid_char(&mask.right, c) {
1100 return false;
1101 }
1102 true
1103 }
1104
1105 #[inline]
1107 fn can_insert_integer_left(&self, mask: &MaskToken, new_cursor: upos_type, c: char) -> bool {
1108 if !mask.peek_left.is_rtol() {
1109 return false;
1110 }
1111 if !mask.right.is_ltor() && !mask.right.is_none() {
1112 return false;
1113 }
1114
1115 let left = &self.mask[new_cursor as usize - 1];
1116 if !self.is_valid_char(&left.right, c) {
1117 return false;
1118 }
1119
1120 let mask0 = &self.mask[left.sub_start as usize];
1121 let g0 = self
1122 .masked
1123 .grapheme_at(TextPosition::new(left.sub_start, 0))
1124 .expect("valid_position")
1125 .expect("grapheme");
1126 if !mask0.right.can_drop(g0.grapheme()) {
1127 return false;
1128 }
1129
1130 true
1131 }
1132
1133 pub fn insert_char(&mut self, c: char) -> bool {
1139 if self.mask.is_empty() {
1140 return false;
1141 }
1142
1143 let cursor = self.masked.cursor();
1144
1145 {
1147 let mask = &self.mask[cursor.x as usize];
1148 if mask.right.is_number() && self.can_insert_sign(mask, cursor.x, c) {
1149 if self.insert_sign(c) {
1150 return true;
1151 }
1152 }
1153 }
1154 {
1155 let mask = &self.mask[cursor.x as usize];
1156 if mask.peek_left.is_number() && (mask.right.is_ltor() || mask.right.is_none()) {
1157 let left = &self.mask[cursor.x as usize - 1];
1158 if self.can_insert_sign(left, cursor.x, c) {
1159 if self.insert_sign(c) {
1160 return true;
1161 }
1162 }
1163 }
1164 }
1165 {
1166 let mask = &self.mask[cursor.x as usize];
1167 if mask.right.is_rtol() {
1168 if self.insert_rtol(c) {
1169 return true;
1170 }
1171 }
1172 }
1173 {
1174 let mask = &self.mask[cursor.x as usize];
1175 if mask.peek_left.is_rtol() && (mask.right.is_ltor() || mask.right.is_none()) {
1176 if self.insert_rtol(c) {
1177 return true;
1178 }
1179 }
1180 }
1181 {
1182 let mask = &self.mask[cursor.x as usize];
1183 if mask.right.is_ltor() {
1184 if self.insert_ltor(c) {
1185 #[allow(clippy::needless_return)]
1186 return true;
1187 }
1188 }
1189 }
1190
1191 false
1192 }
1193
1194 fn insert_ltor(&mut self, c: char) -> bool {
1196 let cursor = self.masked.cursor();
1197
1198 let mask = &self.mask[cursor.x as usize];
1199 let mask9 = &self.mask[mask.sub_end as usize - 1];
1200
1201 let g = self
1203 .masked
1204 .grapheme_at(cursor)
1205 .expect("valid_cursor")
1206 .expect("mask");
1207 if mask.right.is_fraction()
1208 && mask.right.can_overwrite_fraction(g.grapheme())
1209 && self.is_valid_char(&mask.right, c)
1210 {
1211 let frac_mask = &self.mask[cursor.x as usize + 1..mask.sub_end as usize];
1213 let frac_str = self
1214 .masked
1215 .str_slice(TextRange::new((cursor.x + 1, 0), (mask.sub_end, 0)))
1216 .expect("valid_range");
1217 if frac_str == MaskToken::empty_section(frac_mask) {
1218 self.masked.begin_undo_seq();
1219 self.masked
1220 .remove_char_range(TextRange::new(cursor, (cursor.x + 1, 0)))
1221 .expect("valid_cursor");
1222 self.masked.insert_char(cursor, c).expect("valid_cursor");
1223 self.masked.end_undo_seq();
1224 return true;
1225 }
1226 }
1227
1228 let g = self
1229 .masked
1230 .grapheme_at(cursor)
1231 .expect("valid_cursor")
1232 .expect("mask");
1233 if mask.right.can_overwrite(g.grapheme()) && self.is_valid_char(&mask.right, c) {
1234 if mask.right.is_separator() {
1235 self.masked.begin_undo_seq();
1236 let r = if let Some(next) = self.next_section_cursor(cursor.x) {
1237 self.masked.set_cursor(TextPosition::new(next, 0), false)
1238 } else {
1239 self.masked
1240 .set_cursor(TextPosition::new(self.line_width(), 0), false)
1241 };
1242 self.masked.end_undo_seq();
1243 return r;
1244 } else if mask.right == Mask::DecimalSep {
1245 self.masked.begin_undo_seq();
1246 self.masked
1247 .set_cursor(TextPosition::new(cursor.x + 1, 0), false);
1248 self.masked.end_undo_seq();
1249 return true;
1250 } else {
1251 self.masked.begin_undo_seq();
1252 self.masked
1253 .remove_char_range(TextRange::new(cursor, (cursor.x + 1, 0)))
1254 .expect("valid_cursor");
1255 self.masked.insert_char(cursor, c).expect("valid_cursor");
1256 self.masked.end_undo_seq();
1257 return true;
1258 }
1259 }
1260
1261 let g9 = self
1263 .masked
1264 .grapheme_at(TextPosition::new(mask.sub_end - 1, 0))
1265 .expect("valid_pos")
1266 .expect("mask");
1267 if mask9.right.can_drop(g9.grapheme()) && self.is_valid_char(&mask.right, c) {
1268 self.masked.begin_undo_seq();
1269 self.masked
1270 .remove_char_range(TextRange::new((mask.sub_end - 1, 0), (mask.sub_end, 0)))
1271 .expect("valid_range");
1272 self.masked.insert_char(cursor, c).expect("valid_cursor");
1273 self.masked.end_undo_seq();
1274 return true;
1275 }
1276 false
1277 }
1278
1279 fn insert_rtol(&mut self, c: char) -> bool {
1281 let cursor = self.masked.cursor();
1282
1283 let mut mask = &self.mask[cursor.x as usize];
1284
1285 if mask.peek_left.is_rtol() && (mask.right.is_ltor() || mask.right.is_none()) {
1287 mask = &self.mask[cursor.x as usize - 1];
1288 }
1289
1290 let mask0 = &self.mask[mask.sub_start as usize];
1291
1292 let g0 = self
1293 .masked
1294 .grapheme_at(TextPosition::new(mask.sub_start, 0))
1295 .expect("valid_pos")
1296 .expect("grapheme");
1297 if mask0.right.can_drop(g0.grapheme()) && self.is_valid_char(&mask.right, c) {
1298 self.masked.begin_undo_seq();
1299 self.masked
1300 .remove_char_range(TextRange::new((mask.sub_start, 0), (mask.sub_start + 1, 0)))
1301 .expect("valid_position");
1302 self.masked
1303 .insert_char(TextPosition::new(cursor.x - 1, 0), c)
1304 .expect("valid_position");
1305 Self::reformat(&mut self.masked, &self.mask, mask.sub_start..mask.sub_end);
1306 self.masked.end_undo_seq();
1307 return true;
1308 }
1309
1310 false
1311 }
1312
1313 #[allow(clippy::single_match)]
1315 fn insert_sign(&mut self, c: char) -> bool {
1316 let cursor = self.masked.cursor();
1317
1318 let mut mask = &self.mask[cursor.x as usize];
1319 if mask.peek_left.is_number() && (mask.right.is_ltor() || mask.right.is_none()) {
1321 mask = &self.mask[cursor.x as usize - 1];
1322 }
1323
1324 let idx = self.mask[mask.sec_start as usize..mask.sec_end as usize]
1326 .iter()
1327 .enumerate()
1328 .find(|(_, t)| matches!(t.right, Mask::Sign | Mask::Plus))
1329 .map(|(i, _)| mask.sec_start as usize + i);
1330
1331 let idx = if idx.is_none() {
1333 self.masked
1334 .graphemes(
1335 TextRange::new((mask.sec_start, 0), (mask.sec_end, 0)),
1336 TextPosition::new(mask.sec_start, 0),
1337 )
1338 .expect("valid_range")
1339 .enumerate()
1340 .find(|(_, g)| *g == "-" || *g == "+")
1341 .map(|(i, _)| mask.sec_start as usize + i)
1342 } else {
1343 idx
1344 };
1345
1346 let idx = if idx.is_none() {
1347 let mut idx = mask.sec_end - 1;
1349 'f: {
1350 while idx >= mask.sec_start {
1351 if self.mask[idx as usize].right == Mask::Numeric(EditDirection::Rtol) {
1352 let g = self
1353 .grapheme_at(idx)
1354 .expect("valid_position")
1355 .expect("grapheme");
1356
1357 if self.mask[idx as usize].right.can_drop(g.grapheme()) {
1358 break 'f Some(idx as usize);
1359 }
1360 }
1361 idx -= 1;
1362 }
1363 None
1364 }
1365 } else {
1366 idx
1367 };
1368
1369 if let Some(idx) = idx {
1370 let mask_sign = &self.mask[idx];
1371
1372 if c == self.neg_sym() || c == '-' {
1373 let g = self
1375 .masked
1376 .str_slice(TextRange::new(
1377 (idx as upos_type, 0),
1378 (idx as upos_type + 1, 0),
1379 ))
1380 .expect("valid_pos")
1381 .to_string();
1382
1383 self.masked.begin_undo_seq();
1384 self.masked
1385 .remove_char_range(TextRange::new(
1386 (idx as upos_type, 0),
1387 (idx as upos_type + 1, 0),
1388 ))
1389 .expect("valid_range");
1390
1391 let cc = match &mask_sign.right {
1392 Mask::Numeric(_) | Mask::Sign => {
1393 if g == "-" {
1394 ' '
1395 } else {
1396 '-'
1397 }
1398 }
1399 Mask::Plus => {
1400 if g == "-" {
1401 '+'
1402 } else {
1403 '-'
1404 }
1405 }
1406 _ => unreachable!(),
1407 };
1408
1409 self.masked
1410 .insert_char(TextPosition::new(idx as upos_type, 0), cc)
1411 .expect("valid_range");
1412 self.set_cursor(cursor.x, false);
1413 self.masked.end_undo_seq();
1414 true
1415 } else {
1416 false
1417 }
1418 } else {
1419 false
1420 }
1421 }
1422
1423 pub fn remove_prev(&mut self) {
1425 let cursor = self.masked.cursor();
1426
1427 if cursor.x == 0 {
1428 return;
1429 }
1430
1431 let left = &self.mask[cursor.x as usize - 1];
1432
1433 if left.right.is_rtol() {
1434 let sec_empty = if left.right.is_rtol() {
1436 let sec_str = self
1437 .masked
1438 .str_slice(TextRange::new((left.sub_start, 0), (left.sub_end, 0)))
1439 .expect("valid_range");
1440 let sec_mask = &self.mask[left.sub_start as usize..left.sub_end as usize];
1441 sec_str == MaskToken::empty_section(sec_mask)
1442 } else {
1443 false
1444 };
1445
1446 let l0 = &self.mask[left.sub_start as usize];
1447
1448 self.masked.begin_undo_seq();
1449 self.masked
1450 .remove_char_range(TextRange::new((cursor.x - 1, 0), cursor))
1451 .expect("valid_range");
1452 self.masked
1453 .insert_str(TextPosition::new(left.sub_start, 0), &l0.edit)
1454 .expect("valid_position");
1455 Self::reformat(&mut self.masked, &self.mask, left.sub_start..left.sub_end);
1456
1457 if sec_empty {
1461 self.masked
1462 .set_cursor(TextPosition::new(left.sub_start, 0), false);
1463 } else {
1464 }
1466
1467 self.masked.end_undo_seq();
1468 } else if left.right.is_ltor() {
1469 let l9 = &self.mask[left.sub_end as usize - 1];
1470
1471 self.masked.begin_undo_seq();
1472 self.masked
1473 .remove_char_range(TextRange::new((cursor.x - 1, 0), cursor))
1474 .expect("valid_range");
1475 self.masked
1476 .insert_str(TextPosition::new(left.sub_end - 1, 0), &l9.edit)
1477 .expect("valid_position");
1478
1479 Self::reformat(&mut self.masked, &self.mask, left.sub_start..left.sub_end);
1480
1481 self.masked
1482 .set_cursor(TextPosition::new(cursor.x - 1, 0), false);
1483
1484 self.masked.end_undo_seq();
1485 }
1486 }
1487
1488 pub fn remove_next(&mut self) {
1490 let cursor = self.masked.cursor();
1491
1492 if cursor.x as usize == self.mask.len() - 1 {
1493 return;
1494 }
1495
1496 let right = &self.mask[cursor.x as usize];
1497
1498 if right.right.is_rtol() {
1500 let l0 = &self.mask[right.sub_start as usize];
1501
1502 self.masked.begin_undo_seq();
1503 self.masked
1504 .remove_char_range(TextRange::new(cursor, (cursor.x + 1, 0)))
1505 .expect("valid_range");
1506 self.masked
1507 .insert_str(TextPosition::new(right.sub_start, 0), &l0.edit)
1508 .expect("valid_position");
1509 Self::reformat(&mut self.masked, &self.mask, right.sub_start..right.sub_end);
1510
1511 self.masked
1512 .set_cursor(TextPosition::new(cursor.x + 1, 0), false);
1513
1514 self.masked.end_undo_seq();
1515 } else if right.right.is_ltor() {
1516 let sec_str = self
1518 .masked
1519 .str_slice(TextRange::new((right.sub_start, 0), (right.sub_end, 0)))
1520 .expect("valid_range");
1521 let sec_mask = &self.mask[right.sub_start as usize..right.sub_end as usize];
1522 let sec_empty = sec_str == MaskToken::empty_section(sec_mask);
1523
1524 let l9 = &self.mask[right.sub_end as usize - 1];
1525
1526 self.masked.begin_undo_seq();
1527 self.masked
1528 .remove_char_range(TextRange::new(cursor, (cursor.x + 1, 0)))
1529 .expect("valid_range");
1530 self.masked
1531 .insert_str(TextPosition::new(right.sub_end - 1, 0), &l9.edit)
1532 .expect("valid_position");
1533
1534 Self::reformat(&mut self.masked, &self.mask, right.sub_start..right.sub_end);
1535
1536 if sec_empty {
1540 self.masked
1541 .set_cursor(TextPosition::new(right.sub_end, 0), false);
1542 } else {
1543 }
1545
1546 self.masked.end_undo_seq();
1547 }
1548 }
1549
1550 pub fn remove_range(&mut self, range: Range<upos_type>) -> Result<bool, TextError> {
1552 self.masked
1554 .bytes_at_range(TextRange::new((range.start, 0), (range.end, 0)))?;
1555
1556 if range.is_empty() {
1557 return Ok(false);
1558 }
1559
1560 let mask = &self.mask[range.start as usize];
1561 if range.start >= mask.sub_start && range.end <= mask.sub_end {
1562 if mask.right.is_rtol() {
1563 self.masked.begin_undo_seq();
1564 self.masked
1565 .remove_str_range(TextRange::new((range.start, 0), (range.end, 0)))
1566 .expect("valid_range");
1567 let fill_before =
1568 &self.mask[mask.sub_start as usize..mask.sub_start as usize + range.len()];
1569 self.masked
1570 .insert_str(
1571 TextPosition::new(mask.sub_start, 0),
1572 &MaskToken::empty_section(fill_before),
1573 )
1574 .expect("valid_range");
1575 Self::reformat(&mut self.masked, &self.mask, mask.sub_start..mask.sub_end);
1576 self.masked.end_undo_seq();
1577 } else if mask.right.is_ltor() {
1578 self.masked.begin_undo_seq();
1579 self.masked
1580 .remove_str_range(TextRange::new((range.start, 0), (range.end, 0)))
1581 .expect("valid_range");
1582 let fill_after =
1583 &self.mask[mask.sub_end as usize - range.len()..mask.sub_end as usize];
1584 self.masked
1585 .insert_str(
1586 TextPosition::new(mask.sub_end - range.len() as upos_type, 0),
1587 &MaskToken::empty_section(fill_after),
1588 )
1589 .expect("valid_range");
1590 Self::reformat(&mut self.masked, &self.mask, mask.sub_start..mask.sub_end);
1591 self.masked.end_undo_seq();
1592 }
1593
1594 return Ok(true);
1595 }
1596
1597 let mut pos = range.start;
1598 self.masked.begin_undo_seq();
1599 loop {
1600 let mask = &self.mask[pos as usize];
1601
1602 if mask.sub_start < range.start {
1603 if mask.right.is_rtol() {
1605 self.masked
1606 .remove_str_range(TextRange::new((range.start, 0), (mask.sub_end, 0)))
1607 .expect("valid_range");
1608
1609 let len = mask.sub_end - range.start;
1610 let fill_before =
1611 &self.mask[mask.sub_start as usize..(mask.sub_start + len) as usize];
1612 self.masked
1613 .insert_str(
1614 TextPosition::new(mask.sub_start, 0),
1615 &MaskToken::empty_section(fill_before),
1616 )
1617 .expect("valid_range");
1618
1619 Self::reformat(&mut self.masked, &self.mask, mask.sub_start..mask.sub_end);
1620
1621 pos = mask.sub_end;
1622 } else if mask.right.is_ltor() {
1623 self.masked
1624 .remove_str_range(TextRange::new((range.start, 0), (mask.sub_end, 0)))
1625 .expect("valid_range");
1626
1627 let fill_after = &self.mask[range.start as usize..mask.sub_end as usize];
1628 self.masked
1629 .insert_str(
1630 TextPosition::new(range.start, 0),
1631 &MaskToken::empty_section(fill_after),
1632 )
1633 .expect("valid_range");
1634
1635 Self::reformat(&mut self.masked, &self.mask, mask.sub_start..mask.sub_end);
1636
1637 pos = mask.sub_end;
1638 }
1639 } else if mask.sub_end > range.end {
1640 if mask.right.is_rtol() {
1642 self.masked
1643 .remove_str_range(TextRange::new((mask.sub_start, 0), (range.end, 0)))
1644 .expect("valid_range");
1645
1646 let fill_before = &self.mask[mask.sub_start as usize..range.end as usize];
1647 self.masked
1648 .insert_str(
1649 TextPosition::new(mask.sub_start, 0),
1650 &MaskToken::empty_section(fill_before),
1651 )
1652 .expect("valid_range");
1653
1654 Self::reformat(&mut self.masked, &self.mask, mask.sub_start..mask.sub_end);
1655 pos = mask.sub_end;
1656 } else if mask.right.is_ltor() {
1657 self.masked
1658 .remove_str_range(TextRange::new((mask.sub_start, 0), (range.end, 0)))
1659 .expect("valid_range");
1660
1661 let len = range.end - mask.sub_start;
1662 let fill_after =
1663 &self.mask[(mask.sub_end - len) as usize..mask.sub_end as usize];
1664 self.masked
1665 .insert_str(
1666 TextPosition::new(mask.sub_end - len, 0),
1667 &MaskToken::empty_section(fill_after),
1668 )
1669 .expect("valid_range");
1670
1671 pos = mask.sub_end;
1672 }
1673 } else {
1674 self.masked
1676 .remove_str_range(TextRange::new((mask.sub_start, 0), (mask.sub_end, 0)))
1677 .expect("valid_range");
1678
1679 let sec_range = &self.mask[mask.sub_start as usize..mask.sub_end as usize];
1680 self.masked
1681 .insert_str(
1682 TextPosition::new(mask.sub_start, 0),
1683 &MaskToken::empty_section(sec_range),
1684 )
1685 .expect("valid_range");
1686
1687 pos = mask.sub_end;
1689 }
1690
1691 if pos >= range.end {
1692 break;
1693 }
1694 }
1695 self.masked.end_undo_seq();
1696
1697 Ok(true)
1698 }
1699
1700 fn reformat(core: &mut TextCore<TextString>, mask: &[MaskToken], section: Range<upos_type>) {
1703 if mask[section.start as usize].right.is_rtol() {
1704 let cursor = core.cursor();
1705 let anchor = core.anchor();
1706
1707 let sec_str = core
1708 .str_slice(TextRange::new((section.start, 0), (section.end, 0)))
1709 .expect("valid_range");
1710
1711 let sym = NumberSymbols {
1713 decimal_sep: '.',
1714 decimal_grp: Some(','),
1715 negative_sym: '-',
1716 positive_sym: ' ',
1717 exponent_upper_sym: 'E',
1718 exponent_lower_sym: 'e',
1719 currency_sym: CurrencySym::new("$"),
1720 };
1721
1722 let mut clean = String::new();
1724 _ = clean_num(sec_str.as_ref(), &sym, &mut clean);
1725
1726 let mut tok = String::new();
1728 let submask = &mask[section.start as usize..section.end as usize];
1729 for t in submask {
1731 match &t.right {
1732 Mask::Digit0(_) => tok.push('0'),
1733 Mask::Digit(_) => tok.push('9'),
1734 Mask::Numeric(_) => tok.push('#'),
1735 Mask::DecimalSep => tok.push('.'),
1736 Mask::GroupingSep => tok.push(','),
1737 Mask::Sign => tok.push('-'),
1738 Mask::Plus => tok.push('+'),
1739 Mask::Separator(s) => {
1740 for c in s.chars() {
1741 tok.push('\\');
1742 tok.push(c);
1743 }
1744 }
1745 Mask::None => {}
1746 _ => unreachable!("invalid mask"),
1747 }
1748 }
1749
1750 let fmt = match NumberFormat::news(tok, sym) {
1751 Ok(v) => v,
1752 Err(_) => unreachable!("invalid mask"),
1753 };
1754 let mut out = String::new();
1755 match map_num::<_, false>(clean.as_str(), &fmt, fmt.sym(), &mut out) {
1756 Ok(_) => {}
1757 Err(_) => unreachable!("invalid mask"),
1758 }
1759
1760 core.remove_char_range(TextRange::new((section.start, 0), (section.end, 0)))
1761 .expect("valid_range");
1762 core.insert_str(TextPosition::new(section.start, 0), &out)
1763 .expect("valid_position");
1764
1765 core.set_cursor(anchor, false);
1767 core.set_cursor(cursor, true);
1768 } else if mask[section.start as usize].right.is_ltor() {
1769 let cursor = core.cursor();
1770 let anchor = core.anchor();
1771
1772 let sec_str = core
1773 .str_slice(TextRange::new((section.start, 0), (section.end, 0)))
1774 .expect("valid_range");
1775 let sec_mask = &mask[section.start as usize..section.end as usize];
1776 let mut str_new = String::new();
1777 for (g, t) in sec_str.graphemes(true).zip(sec_mask.iter()) {
1778 match t.right {
1779 Mask::Digit0(_) | Mask::Hex0 | Mask::Oct0 | Mask::Dec0 => {
1780 if g == " " {
1781 str_new.push('0');
1782 } else {
1783 str_new.push_str(g);
1784 }
1785 }
1786 _ => {
1787 str_new.push_str(g);
1788 }
1789 }
1790 }
1791
1792 if sec_str != str_new {
1793 core.remove_char_range(TextRange::new((section.start, 0), (section.end, 0)))
1794 .expect("valid_range");
1795 core.insert_str(TextPosition::new(section.start, 0), &str_new)
1796 .expect("valid_position");
1797
1798 core.set_cursor(anchor, false);
1800 core.set_cursor(cursor, true);
1801 }
1802 }
1803 }
1804}
1805
1806mod mask {
1807 use crate::upos_type;
1808 use std::fmt;
1809 use std::fmt::{Debug, Display, Formatter};
1810
1811 #[derive(Clone, Copy, PartialEq, Eq)]
1814 pub(super) enum EditDirection {
1815 Ltor,
1816 Rtol,
1817 }
1818
1819 #[allow(variant_size_differences)]
1821 #[derive(Clone, PartialEq, Eq, Default)]
1822 #[non_exhaustive]
1823 pub(super) enum Mask {
1824 Digit0(EditDirection),
1826 Digit(EditDirection),
1828 Numeric(EditDirection),
1830 DecimalSep,
1831 GroupingSep,
1832 Sign,
1833 Plus,
1834 Hex0,
1835 Hex,
1836 Oct0,
1837 Oct,
1838 Dec0,
1839 Dec,
1840 Letter,
1841 LetterOrDigit,
1842 LetterDigitSpace,
1843 AnyChar,
1844 Separator(Box<str>),
1845 #[default]
1846 None,
1847 }
1848
1849 #[derive(Clone, PartialEq, Eq)]
1860 pub(super) struct MaskToken {
1861 pub sec_id: u16,
1862 pub sec_start: upos_type,
1864 pub sec_end: upos_type,
1866 pub sub_start: upos_type,
1868 pub sub_end: upos_type,
1870
1871 pub peek_left: Mask,
1873 pub right: Mask,
1875
1876 pub edit: Box<str>,
1878 }
1879
1880 impl Debug for EditDirection {
1881 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1882 write!(
1883 f,
1884 "{}",
1885 match self {
1886 EditDirection::Ltor => ">",
1887 EditDirection::Rtol => "<",
1888 }
1889 )
1890 }
1891 }
1892
1893 impl Display for Mask {
1894 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1895 let s = match self {
1896 Mask::Digit0(_) => "0",
1897 Mask::Digit(_) => "9",
1898 Mask::Numeric(_) => "#",
1899 Mask::DecimalSep => ".",
1900 Mask::GroupingSep => ",",
1901 Mask::Sign => "-",
1902 Mask::Plus => "+",
1903 Mask::Hex0 => "H",
1904 Mask::Hex => "h",
1905 Mask::Oct0 => "O",
1906 Mask::Oct => "o",
1907 Mask::Dec0 => "D",
1908 Mask::Dec => "d",
1909 Mask::Letter => "l",
1910 Mask::LetterOrDigit => "a",
1911 Mask::LetterDigitSpace => "c",
1912 Mask::AnyChar => "_",
1913 Mask::Separator(s) => {
1914 write!(f, "\\")?;
1915 s
1916 }
1917 Mask::None => "",
1918 };
1919 write!(f, "{}", s)
1920 }
1921 }
1922
1923 impl Debug for Mask {
1924 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
1925 match self {
1926 Mask::Digit0(d) => {
1927 write!(f, "{:?}0", d)
1928 }
1929 Mask::Digit(d) => {
1930 write!(f, "{:?}9", d)
1931 }
1932 Mask::Numeric(d) => {
1933 write!(f, "{:?}#", d)
1934 }
1935 Mask::DecimalSep => write!(f, "."),
1936 Mask::GroupingSep => write!(f, ","),
1937 Mask::Sign => write!(f, "-"),
1938 Mask::Plus => write!(f, "+"),
1939 Mask::Hex0 => write!(f, "H"),
1940 Mask::Hex => write!(f, "h"),
1941 Mask::Oct0 => write!(f, "O"),
1942 Mask::Oct => write!(f, "o"),
1943 Mask::Dec0 => write!(f, "D"),
1944 Mask::Dec => write!(f, "d"),
1945 Mask::Letter => write!(f, "l"),
1946 Mask::LetterOrDigit => write!(f, "a"),
1947 Mask::LetterDigitSpace => write!(f, "c"),
1948 Mask::AnyChar => write!(f, "_"),
1949 Mask::Separator(s) => {
1950 write!(f, "\\")?;
1951 write!(f, "{}", s)
1952 }
1953 Mask::None => write!(f, ""),
1954 }
1955 }
1956 }
1957
1958 impl EditDirection {
1959 pub(super) fn is_ltor(&self) -> bool {
1960 *self == EditDirection::Ltor
1961 }
1962
1963 pub(super) fn is_rtol(&self) -> bool {
1964 *self == EditDirection::Rtol
1965 }
1966 }
1967
1968 impl Mask {
1969 pub(super) fn is_none(&self) -> bool {
1972 *self == Mask::None
1973 }
1974
1975 #[inline]
1977 pub(super) fn is_ltor(&self) -> bool {
1978 match self {
1979 Mask::Digit0(d) => d.is_ltor(),
1980 Mask::Digit(d) => d.is_ltor(),
1981 Mask::Numeric(d) => d.is_ltor(),
1982 Mask::GroupingSep => false,
1983 Mask::Sign => false,
1984 Mask::Plus => false,
1985 Mask::DecimalSep => true,
1986 Mask::Hex0 => true,
1987 Mask::Hex => true,
1988 Mask::Oct0 => true,
1989 Mask::Oct => true,
1990 Mask::Dec0 => true,
1991 Mask::Dec => true,
1992 Mask::Letter => true,
1993 Mask::LetterOrDigit => true,
1994 Mask::LetterDigitSpace => true,
1995 Mask::AnyChar => true,
1996 Mask::Separator(_) => true,
1997 Mask::None => false,
1998 }
1999 }
2000
2001 #[inline]
2003 pub(super) fn is_rtol(&self) -> bool {
2004 match self {
2005 Mask::Digit0(d) => d.is_rtol(),
2006 Mask::Digit(d) => d.is_rtol(),
2007 Mask::Numeric(d) => d.is_rtol(),
2008 Mask::GroupingSep => true,
2009 Mask::Sign => true,
2010 Mask::Plus => true,
2011 Mask::DecimalSep => false,
2012 Mask::Hex0 => false,
2013 Mask::Hex => false,
2014 Mask::Oct0 => false,
2015 Mask::Oct => false,
2016 Mask::Dec0 => false,
2017 Mask::Dec => false,
2018 Mask::Letter => false,
2019 Mask::LetterOrDigit => false,
2020 Mask::LetterDigitSpace => false,
2021 Mask::AnyChar => false,
2022 Mask::Separator(_) => false,
2023 Mask::None => false,
2024 }
2025 }
2026
2027 #[inline]
2029 pub(super) fn is_number(&self) -> bool {
2030 match self {
2031 Mask::Digit0(_)
2032 | Mask::Digit(_)
2033 | Mask::Numeric(_)
2034 | Mask::DecimalSep
2035 | Mask::GroupingSep
2036 | Mask::Sign
2037 | Mask::Plus => true,
2038 Mask::None => false,
2039 _ => false,
2040 }
2041 }
2042
2043 #[inline]
2045 pub(super) fn is_separator(&self) -> bool {
2046 match self {
2047 Mask::Separator(_) => true,
2048 Mask::None => false,
2049 _ => false,
2050 }
2051 }
2052
2053 #[inline]
2054 pub(super) fn is_fraction(&self) -> bool {
2055 match self {
2056 Mask::Digit0(d) | Mask::Digit(d) | Mask::Numeric(d) => d.is_ltor(),
2057 Mask::None => false,
2058 _ => false,
2059 }
2060 }
2061
2062 #[inline]
2064 pub(super) fn sub_section(&self) -> u8 {
2065 match self {
2066 Mask::Digit0(_) => 0,
2067 Mask::Digit(_) => 0,
2068 Mask::Numeric(_) => 0,
2069 Mask::GroupingSep => 0,
2070
2071 Mask::Sign => 1,
2072
2073 Mask::Plus => 2,
2074
2075 Mask::DecimalSep => 3,
2076
2077 Mask::Hex0 => 4,
2078 Mask::Hex => 4,
2079
2080 Mask::Oct0 => 5,
2081 Mask::Oct => 5,
2082
2083 Mask::Dec0 => 6,
2084 Mask::Dec => 6,
2085
2086 Mask::Letter => 7,
2087 Mask::LetterOrDigit => 8,
2088 Mask::LetterDigitSpace => 9,
2089 Mask::AnyChar => 10,
2090
2091 Mask::Separator(_) => 11,
2092
2093 Mask::None => 12,
2094 }
2095 }
2096
2097 #[inline]
2099 pub(super) fn section(&self) -> u8 {
2100 match self {
2101 Mask::Digit0(_) => 0,
2102 Mask::Digit(_) => 0,
2103 Mask::Numeric(_) => 0,
2104 Mask::GroupingSep => 0,
2105 Mask::Sign => 0,
2106 Mask::Plus => 0,
2107 Mask::DecimalSep => 0,
2108
2109 Mask::Hex0 => 1,
2110 Mask::Hex => 1,
2111 Mask::Oct0 => 1,
2112 Mask::Oct => 1,
2113 Mask::Dec0 => 1,
2114 Mask::Dec => 1,
2115 Mask::Letter => 1,
2116 Mask::LetterOrDigit => 1,
2117 Mask::LetterDigitSpace => 1,
2118 Mask::AnyChar => 1,
2119
2120 Mask::Separator(_) => 2,
2121 Mask::None => 3,
2122 }
2123 }
2124
2125 #[inline]
2127 pub(super) fn can_overwrite_fraction(&self, c: &str) -> bool {
2128 match self {
2129 Mask::Digit0(_) => c == "0",
2130 Mask::Digit(_) | Mask::Numeric(_) => c == " ",
2131 Mask::DecimalSep => false,
2132 Mask::GroupingSep => false,
2133 Mask::Sign => false,
2134 Mask::Plus => false,
2135 Mask::Hex0 => false,
2136 Mask::Hex => false,
2137 Mask::Oct0 => false,
2138 Mask::Oct => false,
2139 Mask::Dec0 => false,
2140 Mask::Dec => false,
2141 Mask::Letter => false,
2142 Mask::LetterOrDigit => false,
2143 Mask::LetterDigitSpace => false,
2144 Mask::AnyChar => false,
2145 Mask::Separator(_) => false,
2146 Mask::None => false,
2147 }
2148 }
2149
2150 #[inline]
2152 pub(super) fn can_overwrite(&self, c: &str) -> bool {
2153 match self {
2154 Mask::Digit0(_) | Mask::Digit(_) | Mask::Numeric(_) => false,
2155 Mask::DecimalSep => "." == c,
2156 Mask::GroupingSep => false,
2157 Mask::Sign => "-" == c || " " == c,
2158 Mask::Plus => "-" == c || "+" == c || " " == c,
2159 Mask::Hex0 => c == "0",
2160 Mask::Hex => false,
2161 Mask::Oct0 => c == "0",
2162 Mask::Oct => false,
2163 Mask::Dec0 => c == "0",
2164 Mask::Dec => false,
2165 Mask::Letter => false,
2166 Mask::LetterOrDigit => false,
2167 Mask::LetterDigitSpace => false,
2168 Mask::AnyChar => false,
2169 Mask::Separator(sep) => sep.as_ref() == c,
2170 Mask::None => false,
2171 }
2172 }
2173
2174 #[inline]
2176 pub(super) fn can_drop(&self, c: &str) -> bool {
2177 match self {
2178 Mask::Digit0(_) => c == "0",
2179 Mask::Digit(_) => c == " ",
2180 Mask::Numeric(_) => c == " ",
2181 Mask::DecimalSep => false,
2182 Mask::Sign => false,
2183 Mask::Plus => false,
2184 Mask::GroupingSep => true,
2185 Mask::Hex0 => c == "0",
2186 Mask::Hex => c == " ",
2187 Mask::Oct0 => c == "0",
2188 Mask::Oct => c == " ",
2189 Mask::Dec0 => c == "0",
2190 Mask::Dec => c == " ",
2191 Mask::Letter => c == " ",
2192 Mask::LetterOrDigit => c == " ",
2193 Mask::LetterDigitSpace => c == " ",
2194 Mask::AnyChar => c == " ",
2195 Mask::Separator(_sep) => false,
2196 Mask::None => false,
2197 }
2198 }
2199
2200 #[inline]
2202 pub(super) fn edit_value(&self) -> &str {
2203 match self {
2204 Mask::Digit0(_) => "0",
2205 Mask::Digit(_) => " ",
2206 Mask::Numeric(_) => " ",
2207 Mask::DecimalSep => ".",
2208 Mask::GroupingSep => " ", Mask::Sign => " ",
2210 Mask::Plus => "+",
2211 Mask::Hex0 => "0",
2212 Mask::Hex => " ",
2213 Mask::Oct0 => "0",
2214 Mask::Oct => " ",
2215 Mask::Dec0 => "0",
2216 Mask::Dec => " ",
2217 Mask::Letter => " ",
2218 Mask::LetterOrDigit => " ",
2219 Mask::LetterDigitSpace => " ",
2220 Mask::AnyChar => " ",
2221 Mask::Separator(g) => g.as_ref(),
2222 Mask::None => "",
2223 }
2224 }
2225 }
2226
2227 impl Debug for MaskToken {
2228 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2229 write!(
2230 f,
2231 "Mask #{}:{}-{} {:?} | {:?}",
2232 self.sec_id, self.sub_start, self.sub_end, self.peek_left, self.right
2233 )
2234 }
2235 }
2236
2237 impl MaskToken {
2238 #[inline]
2240 pub(super) fn is_integer_part(&self) -> bool {
2241 self.peek_left.is_rtol() || self.peek_left.is_none() && self.right.is_rtol()
2242 }
2243
2244 pub(super) fn empty_section(mask: &[MaskToken]) -> String {
2246 let mut buf = String::new();
2247 for m in mask {
2248 buf.push_str(&m.edit);
2249 }
2250 buf
2251 }
2252 }
2253}