1use std::fmt::Debug;
2
3use crate::{attrs::Attrs, term::BufWrite as _, TermReplySender};
4use compact_str::ToCompactString;
5use termwiz::escape::{
6 csi::{
7 CsiParam, Cursor, CursorStyle, DecPrivateMode, DecPrivateModeCode, Edit,
8 EraseInDisplay, EraseInLine, Sgr, TerminalMode, TerminalModeCode, Window,
9 },
10 Action, ControlCode, DeviceControlMode, Esc, EscCode, OneBased,
11 OperatingSystemCommand, CSI,
12};
13use unicode_width::UnicodeWidthChar as _;
14
15const MODE_APPLICATION_KEYPAD: u8 = 0b0000_0001;
16const MODE_APPLICATION_CURSOR: u8 = 0b0000_0010;
17const MODE_HIDE_CURSOR: u8 = 0b0000_0100;
18const MODE_ALTERNATE_SCREEN: u8 = 0b0000_1000;
19const MODE_BRACKETED_PASTE: u8 = 0b0001_0000;
20
21#[derive(Clone, Debug)]
22pub enum CharSet {
23 Ascii,
24 Uk,
25 DecLineDrawing,
26}
27
28#[derive(Copy, Clone, Debug, Eq, PartialEq)]
30pub enum MouseProtocolMode {
31 None,
33
34 Press,
37
38 PressRelease,
41
42 ButtonMotion,
47
48 AnyMotion,
52 }
54
55impl Default for MouseProtocolMode {
56 fn default() -> Self {
57 Self::None
58 }
59}
60
61#[derive(Copy, Clone, Debug, Eq, PartialEq)]
63pub enum MouseProtocolEncoding {
64 Default,
66
67 Utf8,
69
70 Sgr,
72 }
74
75impl Default for MouseProtocolEncoding {
76 fn default() -> Self {
77 Self::Default
78 }
79}
80
81#[derive(Clone, Debug)]
83pub struct Screen<Reply: TermReplySender> {
84 reply_sender: Reply,
85
86 grid: crate::grid::Grid,
87 alternate_grid: crate::grid::Grid,
88
89 attrs: crate::attrs::Attrs,
90 saved_attrs: crate::attrs::Attrs,
91
92 title: String,
93 icon_name: String,
94
95 cursor_style: CursorStyle,
96
97 modes: u8,
98 mouse_protocol_mode: MouseProtocolMode,
99 mouse_protocol_encoding: MouseProtocolEncoding,
100
101 g0: CharSet,
102 g1: CharSet,
103 shift_out: bool,
104
105 insert: bool,
107
108 audible_bell_count: usize,
109 visual_bell_count: usize,
110
111 errors: usize,
112}
113
114impl<Reply: TermReplySender> Screen<Reply> {
115 #[must_use]
116 pub fn get_selected_text(
117 &self,
118 low_x: i32,
119 low_y: i32,
120 high_x: i32,
121 high_y: i32,
122 ) -> String {
123 self.grid().get_selected_text(low_x, low_y, high_x, high_y)
124 }
125
126 pub(crate) fn new(
127 size: crate::grid::Size,
128 scrollback_len: usize,
129 reply_sender: Reply,
130 ) -> Self {
131 let mut grid = crate::grid::Grid::new(size, scrollback_len);
132 grid.allocate_rows();
133 Self {
134 reply_sender,
135 grid,
136 alternate_grid: crate::grid::Grid::new(size, 0),
137
138 attrs: crate::attrs::Attrs::default(),
139 saved_attrs: crate::attrs::Attrs::default(),
140
141 title: String::default(),
142 icon_name: String::default(),
143
144 cursor_style: CursorStyle::Default,
145
146 modes: 0,
147 mouse_protocol_mode: MouseProtocolMode::default(),
148 mouse_protocol_encoding: MouseProtocolEncoding::default(),
149
150 g0: CharSet::Ascii,
151 g1: CharSet::Ascii,
152 shift_out: false,
153
154 insert: false,
155
156 audible_bell_count: 0,
157 visual_bell_count: 0,
158
159 errors: 0,
160 }
161 }
162
163 pub(crate) fn set_size(&mut self, rows: u16, cols: u16) {
164 self.grid.set_size(crate::grid::Size { rows, cols });
165 self
166 .alternate_grid
167 .set_size(crate::grid::Size { rows, cols });
168 }
169
170 #[must_use]
174 pub fn size(&self) -> (u16, u16) {
175 let size = self.grid().size();
176 (size.rows, size.cols)
177 }
178
179 #[must_use]
184 pub fn scrollback(&self) -> usize {
185 self.grid().scrollback()
186 }
187
188 #[must_use]
189 pub fn scrollback_len(&self) -> usize {
190 self.grid().scrollback_len()
191 }
192
193 pub fn set_scrollback(&mut self, rows: usize) {
194 self.grid_mut().set_scrollback(rows);
195 }
196
197 #[must_use]
202 pub fn contents(&self) -> String {
203 let mut contents = String::new();
204 self.write_contents(&mut contents);
205 contents
206 }
207
208 fn write_contents(&self, contents: &mut String) {
209 self.grid().write_contents(contents);
210 }
211
212 pub fn rows(
220 &self,
221 start: u16,
222 width: u16,
223 ) -> impl Iterator<Item = String> + '_ {
224 self.grid().visible_rows().map(move |row| {
225 let mut contents = String::new();
226 row.write_contents(&mut contents, start, width, false);
227 contents
228 })
229 }
230
231 #[must_use]
238 pub fn contents_between(
239 &self,
240 start_row: u16,
241 start_col: u16,
242 end_row: u16,
243 end_col: u16,
244 ) -> String {
245 match start_row.cmp(&end_row) {
246 std::cmp::Ordering::Less => {
247 let (_, cols) = self.size();
248 let mut contents = String::new();
249 for (i, row) in self
250 .grid()
251 .visible_rows()
252 .enumerate()
253 .skip(usize::from(start_row))
254 .take(usize::from(end_row) - usize::from(start_row) + 1)
255 {
256 if i == usize::from(start_row) {
257 row.write_contents(
258 &mut contents,
259 start_col,
260 cols - start_col,
261 false,
262 );
263 if !row.wrapped() {
264 contents.push('\n');
265 }
266 } else if i == usize::from(end_row) {
267 row.write_contents(&mut contents, 0, end_col, false);
268 } else {
269 row.write_contents(&mut contents, 0, cols, false);
270 if !row.wrapped() {
271 contents.push('\n');
272 }
273 }
274 }
275 contents
276 }
277 std::cmp::Ordering::Equal => {
278 if start_col < end_col {
279 self
280 .rows(start_col, end_col - start_col)
281 .nth(usize::from(start_row))
282 .unwrap_or_else(String::new)
283 } else {
284 String::new()
285 }
286 }
287 std::cmp::Ordering::Greater => String::new(),
288 }
289 }
290
291 #[must_use]
295 pub fn state_formatted(&self) -> Vec<u8> {
296 let mut contents = vec![];
297 self.write_contents_formatted(&mut contents);
298 self.write_input_mode_formatted(&mut contents);
299 self.write_title_formatted(&mut contents);
300 contents
301 }
302
303 #[must_use]
308 pub fn state_diff(&self, prev: &Self) -> Vec<u8> {
309 let mut contents = vec![];
310 self.write_contents_diff(&mut contents, prev);
311 self.write_input_mode_diff(&mut contents, prev);
312 self.write_title_diff(&mut contents, prev);
313 self.write_bells_diff(&mut contents, prev);
314 contents
315 }
316
317 #[must_use]
323 pub fn contents_formatted(&self) -> Vec<u8> {
324 let mut contents = vec![];
325 self.write_contents_formatted(&mut contents);
326 contents
327 }
328
329 fn write_contents_formatted(&self, contents: &mut Vec<u8>) {
330 crate::term::HideCursor::new(self.hide_cursor()).write_buf(contents);
331 let prev_attrs = self.grid().write_contents_formatted(contents);
332 self.attrs.write_escape_code_diff(contents, &prev_attrs);
333 }
334
335 #[allow(clippy::missing_panics_doc)]
347 pub fn rows_formatted(
348 &self,
349 start: u16,
350 width: u16,
351 ) -> impl Iterator<Item = Vec<u8>> + '_ {
352 let mut wrapping = false;
353 self.grid().visible_rows().enumerate().map(move |(i, row)| {
354 let i = i.try_into().unwrap();
357 let mut contents = vec![];
358 row.write_contents_formatted(
359 &mut contents,
360 start,
361 width,
362 i,
363 wrapping,
364 None,
365 None,
366 );
367 if start == 0 && width == self.grid.size().cols {
368 wrapping = row.wrapped();
369 }
370 contents
371 })
372 }
373
374 #[must_use]
385 pub fn contents_diff(&self, prev: &Self) -> Vec<u8> {
386 let mut contents = vec![];
387 self.write_contents_diff(&mut contents, prev);
388 contents
389 }
390
391 fn write_contents_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
392 if self.hide_cursor() != prev.hide_cursor() {
393 crate::term::HideCursor::new(self.hide_cursor()).write_buf(contents);
394 }
395 let prev_attrs =
396 self
397 .grid()
398 .write_contents_diff(contents, prev.grid(), prev.attrs);
399 self.attrs.write_escape_code_diff(contents, &prev_attrs);
400 }
401
402 #[allow(clippy::missing_panics_doc)]
412 pub fn rows_diff<'a>(
413 &'a self,
414 prev: &'a Self,
415 start: u16,
416 width: u16,
417 ) -> impl Iterator<Item = Vec<u8>> + 'a {
418 self
419 .grid()
420 .visible_rows()
421 .zip(prev.grid().visible_rows())
422 .enumerate()
423 .map(move |(i, (row, prev_row))| {
424 let i = i.try_into().unwrap();
427 let mut contents = vec![];
428 row.write_contents_diff(
429 &mut contents,
430 prev_row,
431 start,
432 width,
433 i,
434 false,
435 false,
436 crate::grid::Pos { row: i, col: start },
437 crate::attrs::Attrs::default(),
438 );
439 contents
440 })
441 }
442
443 #[must_use]
452 pub fn input_mode_formatted(&self) -> Vec<u8> {
453 let mut contents = vec![];
454 self.write_input_mode_formatted(&mut contents);
455 contents
456 }
457
458 fn write_input_mode_formatted(&self, contents: &mut Vec<u8>) {
459 crate::term::ApplicationKeypad::new(self.mode(MODE_APPLICATION_KEYPAD))
460 .write_buf(contents);
461 crate::term::ApplicationCursor::new(self.mode(MODE_APPLICATION_CURSOR))
462 .write_buf(contents);
463 crate::term::BracketedPaste::new(self.mode(MODE_BRACKETED_PASTE))
464 .write_buf(contents);
465 crate::term::MouseProtocolMode::new(
466 self.mouse_protocol_mode,
467 MouseProtocolMode::None,
468 )
469 .write_buf(contents);
470 crate::term::MouseProtocolEncoding::new(
471 self.mouse_protocol_encoding,
472 MouseProtocolEncoding::Default,
473 )
474 .write_buf(contents);
475 }
476
477 #[must_use]
481 pub fn input_mode_diff(&self, prev: &Self) -> Vec<u8> {
482 let mut contents = vec![];
483 self.write_input_mode_diff(&mut contents, prev);
484 contents
485 }
486
487 fn write_input_mode_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
488 if self.mode(MODE_APPLICATION_KEYPAD) != prev.mode(MODE_APPLICATION_KEYPAD)
489 {
490 crate::term::ApplicationKeypad::new(self.mode(MODE_APPLICATION_KEYPAD))
491 .write_buf(contents);
492 }
493 if self.mode(MODE_APPLICATION_CURSOR) != prev.mode(MODE_APPLICATION_CURSOR)
494 {
495 crate::term::ApplicationCursor::new(self.mode(MODE_APPLICATION_CURSOR))
496 .write_buf(contents);
497 }
498 if self.mode(MODE_BRACKETED_PASTE) != prev.mode(MODE_BRACKETED_PASTE) {
499 crate::term::BracketedPaste::new(self.mode(MODE_BRACKETED_PASTE))
500 .write_buf(contents);
501 }
502 crate::term::MouseProtocolMode::new(
503 self.mouse_protocol_mode,
504 prev.mouse_protocol_mode,
505 )
506 .write_buf(contents);
507 crate::term::MouseProtocolEncoding::new(
508 self.mouse_protocol_encoding,
509 prev.mouse_protocol_encoding,
510 )
511 .write_buf(contents);
512 }
513
514 #[must_use]
517 pub fn title_formatted(&self) -> Vec<u8> {
518 let mut contents = vec![];
519 self.write_title_formatted(&mut contents);
520 contents
521 }
522
523 fn write_title_formatted(&self, contents: &mut Vec<u8>) {
524 crate::term::ChangeTitle::new(&self.icon_name, &self.title, "", "")
525 .write_buf(contents);
526 }
527
528 #[must_use]
532 pub fn title_diff(&self, prev: &Self) -> Vec<u8> {
533 let mut contents = vec![];
534 self.write_title_diff(&mut contents, prev);
535 contents
536 }
537
538 fn write_title_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
539 crate::term::ChangeTitle::new(
540 &self.icon_name,
541 &self.title,
542 &prev.icon_name,
543 &prev.title,
544 )
545 .write_buf(contents);
546 }
547
548 #[must_use]
552 pub fn bells_diff(&self, prev: &Self) -> Vec<u8> {
553 let mut contents = vec![];
554 self.write_bells_diff(&mut contents, prev);
555 contents
556 }
557
558 fn write_bells_diff(&self, contents: &mut Vec<u8>, prev: &Self) {
559 if self.audible_bell_count != prev.audible_bell_count {
560 crate::term::AudibleBell.write_buf(contents);
561 }
562 if self.visual_bell_count != prev.visual_bell_count {
563 crate::term::VisualBell.write_buf(contents);
564 }
565 }
566
567 #[must_use]
584 pub fn attributes_formatted(&self) -> Vec<u8> {
585 let mut contents = vec![];
586 self.write_attributes_formatted(&mut contents);
587 contents
588 }
589
590 fn write_attributes_formatted(&self, contents: &mut Vec<u8>) {
591 crate::term::ClearAttrs.write_buf(contents);
592 self
593 .attrs
594 .write_escape_code_diff(contents, &crate::attrs::Attrs::default());
595 }
596
597 #[must_use]
601 pub fn cursor_position(&self) -> (u16, u16) {
602 let pos = self.grid().pos();
603 (pos.row, pos.col)
604 }
605
606 #[must_use]
622 pub fn cursor_state_formatted(&self) -> Vec<u8> {
623 let mut contents = vec![];
624 self.write_cursor_state_formatted(&mut contents);
625 contents
626 }
627
628 fn write_cursor_state_formatted(&self, contents: &mut Vec<u8>) {
629 crate::term::HideCursor::new(self.hide_cursor()).write_buf(contents);
630 self
631 .grid()
632 .write_cursor_position_formatted(contents, None, None);
633
634 }
641
642 #[must_use]
645 pub fn cell(&self, row: u16, col: u16) -> Option<&crate::cell::Cell> {
646 self.grid().visible_cell(crate::grid::Pos { row, col })
647 }
648
649 #[must_use]
651 pub fn row_wrapped(&self, row: u16) -> bool {
652 self
653 .grid()
654 .visible_row(row)
655 .is_some_and(crate::row::Row::wrapped)
656 }
657
658 #[must_use]
660 pub fn title(&self) -> &str {
661 &self.title
662 }
663
664 #[must_use]
666 pub fn icon_name(&self) -> &str {
667 &self.icon_name
668 }
669
670 #[must_use]
671 pub fn cursor_style(&self) -> CursorStyle {
672 self.cursor_style
673 }
674
675 #[must_use]
684 pub fn audible_bell_count(&self) -> usize {
685 self.audible_bell_count
686 }
687
688 #[must_use]
697 pub fn visual_bell_count(&self) -> usize {
698 self.visual_bell_count
699 }
700
701 #[must_use]
707 pub fn errors(&self) -> usize {
708 self.errors
709 }
710
711 #[must_use]
713 pub fn alternate_screen(&self) -> bool {
714 self.mode(MODE_ALTERNATE_SCREEN)
715 }
716
717 #[must_use]
719 pub fn application_keypad(&self) -> bool {
720 self.mode(MODE_APPLICATION_KEYPAD)
721 }
722
723 #[must_use]
725 pub fn application_cursor(&self) -> bool {
726 self.mode(MODE_APPLICATION_CURSOR)
727 }
728
729 #[must_use]
731 pub fn hide_cursor(&self) -> bool {
732 self.mode(MODE_HIDE_CURSOR)
733 }
734
735 #[must_use]
737 pub fn bracketed_paste(&self) -> bool {
738 self.mode(MODE_BRACKETED_PASTE)
739 }
740
741 #[must_use]
743 pub fn mouse_protocol_mode(&self) -> MouseProtocolMode {
744 self.mouse_protocol_mode
745 }
746
747 #[must_use]
749 pub fn mouse_protocol_encoding(&self) -> MouseProtocolEncoding {
750 self.mouse_protocol_encoding
751 }
752
753 #[must_use]
755 pub fn fgcolor(&self) -> crate::attrs::Color {
756 self.attrs.fgcolor
757 }
758
759 #[must_use]
761 pub fn bgcolor(&self) -> crate::attrs::Color {
762 self.attrs.bgcolor
763 }
764
765 #[must_use]
768 pub fn bold(&self) -> bool {
769 self.attrs.bold()
770 }
771
772 #[must_use]
775 pub fn italic(&self) -> bool {
776 self.attrs.italic()
777 }
778
779 #[must_use]
782 pub fn underline(&self) -> bool {
783 self.attrs.underline()
784 }
785
786 #[must_use]
789 pub fn inverse(&self) -> bool {
790 self.attrs.inverse()
791 }
792
793 fn grid(&self) -> &crate::grid::Grid {
794 if self.mode(MODE_ALTERNATE_SCREEN) {
795 &self.alternate_grid
796 } else {
797 &self.grid
798 }
799 }
800
801 fn grid_mut(&mut self) -> &mut crate::grid::Grid {
802 if self.mode(MODE_ALTERNATE_SCREEN) {
803 &mut self.alternate_grid
804 } else {
805 &mut self.grid
806 }
807 }
808
809 fn enter_alternate_grid(&mut self) {
810 self.grid_mut().set_scrollback(0);
811 self.set_mode(MODE_ALTERNATE_SCREEN);
812 self.alternate_grid.allocate_rows();
813 }
814
815 fn exit_alternate_grid(&mut self) {
816 self.clear_mode(MODE_ALTERNATE_SCREEN);
817 }
818
819 fn save_cursor(&mut self) {
820 self.grid_mut().save_cursor();
821 self.saved_attrs = self.attrs;
822 }
823
824 fn restore_cursor(&mut self) {
825 self.grid_mut().restore_cursor();
826 self.attrs = self.saved_attrs;
827 }
828
829 fn set_mode(&mut self, mode: u8) {
830 self.modes |= mode;
831 }
832
833 fn clear_mode(&mut self, mode: u8) {
834 self.modes &= !mode;
835 }
836
837 fn mode(&self, mode: u8) -> bool {
838 self.modes & mode != 0
839 }
840
841 fn set_mouse_mode(&mut self, mode: MouseProtocolMode) {
842 self.mouse_protocol_mode = mode;
843 }
844
845 fn clear_mouse_mode(&mut self, mode: MouseProtocolMode) {
846 if self.mouse_protocol_mode == mode {
847 self.mouse_protocol_mode = MouseProtocolMode::default();
848 }
849 }
850
851 fn set_mouse_encoding(&mut self, encoding: MouseProtocolEncoding) {
852 self.mouse_protocol_encoding = encoding;
853 }
854
855 fn clear_mouse_encoding(&mut self, encoding: MouseProtocolEncoding) {
856 if self.mouse_protocol_encoding == encoding {
857 self.mouse_protocol_encoding = MouseProtocolEncoding::default();
858 }
859 }
860
861 #[must_use]
862 pub fn is_wide_continuation(&self, row: u16, col: u16) -> bool {
863 self
864 .grid()
865 .is_wide_continuation(crate::grid::Pos { row, col })
866 }
867}
868
869impl<Reply: TermReplySender + Clone> Screen<Reply> {
870 fn text(&mut self, c: char) {
871 let pos = self.grid().pos();
872 let size = self.grid().size();
873 let attrs = self.attrs;
874
875 let width = c.width();
876 if width.is_none() && (u32::from(c)) < 256 {
877 return;
879 }
880 let width = width
881 .unwrap_or(1)
882 .try_into()
883 .unwrap();
885
886 let mut wrap = false;
895 if pos.col > size.cols - width {
896 let last_cell_pos = crate::grid::Pos {
897 row: pos.row,
898 col: size.cols - 1,
899 };
900 let last_cell = self
901 .grid()
902 .drawing_cell(last_cell_pos)
903 .unwrap();
907 if last_cell.has_contents()
908 || self.grid().is_wide_continuation(last_cell_pos)
909 {
910 wrap = true;
911 }
912 }
913 self.grid_mut().col_wrap(width, wrap);
914 let pos = self.grid().pos();
915
916 if width == 0 {
917 if pos.col > 0 {
918 let prev_cell_pos = crate::grid::Pos {
919 row: pos.row,
920 col: pos.col - 1,
921 };
922 let prev_cell_pos = if self.grid().is_wide_continuation(prev_cell_pos) {
923 crate::grid::Pos {
924 row: pos.row,
925 col: pos.col - 2,
926 }
927 } else {
928 prev_cell_pos
929 };
930 let prev_cell = self
931 .grid_mut()
932 .drawing_cell_mut(prev_cell_pos)
933 .unwrap();
939 prev_cell.append(c);
940 } else if pos.row > 0 {
941 let prev_row = self
942 .grid()
943 .drawing_row(pos.row - 1)
944 .unwrap();
949 if prev_row.wrapped() {
950 let prev_cell_pos = crate::grid::Pos {
951 row: pos.row - 1,
952 col: size.cols - 1,
953 };
954 let prev_cell_pos = if self.grid().is_wide_continuation(prev_cell_pos)
955 {
956 crate::grid::Pos {
957 row: pos.row - 1,
958 col: size.cols - 2,
959 }
960 } else {
961 prev_cell_pos
962 };
963 let prev_cell = self
964 .grid_mut()
965 .drawing_cell_mut(prev_cell_pos)
966 .unwrap();
975 prev_cell.append(c);
976 }
977 }
978 } else {
979 if self.grid().is_wide_continuation(pos) {
980 let prev_cell = self
981 .grid_mut()
982 .drawing_cell_mut(crate::grid::Pos {
983 row: pos.row,
984 col: pos.col - 1,
985 })
986 .unwrap();
994 prev_cell.clear(attrs);
995 }
996
997 if self
998 .grid()
999 .drawing_cell(pos)
1000 .unwrap()
1005 .is_wide()
1006 {
1007 if let Some(next_cell) =
1008 self.grid_mut().drawing_cell_mut(crate::grid::Pos {
1009 row: pos.row,
1010 col: pos.col + 1,
1011 })
1012 {
1013 next_cell.set(' ', attrs);
1014 }
1015 }
1016
1017 let cell = self
1018 .grid_mut()
1019 .drawing_cell_mut(pos)
1020 .unwrap();
1025 cell.set(c, attrs);
1026 self.grid_mut().col_inc(1);
1027 if width > 1 {
1028 let pos = self.grid().pos();
1029 if self
1030 .grid()
1031 .drawing_cell(pos)
1032 .unwrap()
1040 .is_wide()
1041 {
1042 let next_next_pos = crate::grid::Pos {
1043 row: pos.row,
1044 col: pos.col + 1,
1045 };
1046 let next_next_cell = self
1047 .grid_mut()
1048 .drawing_cell_mut(next_next_pos)
1049 .unwrap();
1060 next_next_cell.clear(attrs);
1061 if next_next_pos.col == size.cols - 1 {
1062 self
1063 .grid_mut()
1064 .drawing_row_mut(pos.row)
1065 .unwrap()
1067 .wrap(false);
1068 }
1069 }
1070 let next_cell = self
1071 .grid_mut()
1072 .drawing_cell_mut(pos)
1073 .unwrap();
1081 next_cell.clear(crate::attrs::Attrs::default());
1082 self.grid_mut().col_inc(1);
1083 }
1084 }
1085 }
1086
1087 fn bel(&mut self) {
1090 self.audible_bell_count += 1;
1091 }
1092
1093 fn tab(&mut self) {
1094 self.grid_mut().col_tab();
1095 }
1096
1097 fn decsc(&mut self) {
1101 self.save_cursor();
1102 }
1103
1104 fn decrc(&mut self) {
1106 self.restore_cursor();
1107 }
1108
1109 fn deckpam(&mut self) {
1111 self.set_mode(MODE_APPLICATION_KEYPAD);
1112 }
1113
1114 fn ri(&mut self) {
1116 self.grid_mut().row_dec_scroll(1);
1117 }
1118
1119 fn ris(&mut self) {
1121 let title = self.title.clone();
1122 let icon_name = self.icon_name.clone();
1123 let audible_bell_count = self.audible_bell_count;
1124 let visual_bell_count = self.visual_bell_count;
1125 let errors = self.errors;
1126
1127 *self = Self::new(
1128 self.grid.size(),
1129 self.grid.scrollback_len(),
1130 self.reply_sender.clone(),
1131 );
1132
1133 self.title = title;
1134 self.icon_name = icon_name;
1135 self.audible_bell_count = audible_bell_count;
1136 self.visual_bell_count = visual_bell_count;
1137 self.errors = errors;
1138 }
1139
1140 fn vb(&mut self) {
1142 self.visual_bell_count += 1;
1143 }
1144
1145 fn ich(&mut self, count: u16) {
1149 self.grid_mut().insert_cells(count);
1150 }
1151
1152 fn ed(&mut self, mode: u16) {
1154 let attrs = self.attrs;
1155 match mode {
1156 0 => self.grid_mut().erase_all_forward(attrs),
1157 1 => self.grid_mut().erase_all_backward(attrs),
1158 2 => self.grid_mut().erase_all(attrs),
1159 n => {
1160 log::debug!("unhandled ED mode: {n}");
1161 }
1162 }
1163 }
1164
1165 fn decsed(&mut self, mode: u16) {
1167 self.ed(mode);
1168 }
1169
1170 fn el(&mut self, mode: u16) {
1172 let attrs = self.attrs;
1173 match mode {
1174 0 => self.grid_mut().erase_row_forward(attrs),
1175 1 => self.grid_mut().erase_row_backward(attrs),
1176 2 => self.grid_mut().erase_row(attrs),
1177 n => {
1178 log::debug!("unhandled EL mode: {n}");
1179 }
1180 }
1181 }
1182
1183 fn decsel(&mut self, mode: u16) {
1185 self.el(mode);
1186 }
1187}
1188
1189macro_rules! skip {
1190 ($fmt:expr) => {
1191 {
1192 use std::fmt::Write;
1193 let mut output = String::new();
1194 write!(output, $fmt).unwrap();
1195 log::debug!("Skip seq: {}", output);
1196 }
1197 };
1198 ($fmt:expr, $($arg:tt)*) => {
1199 {
1200 use std::fmt::Write;
1201 let mut output = String::new();
1202 write!(output, $fmt, $($arg)*).unwrap();
1203 log::debug!("Skip seq: {}", output);
1204 }
1205 };
1206}
1207
1208#[allow(clippy::match_same_arms, clippy::semicolon_if_nothing_returned)]
1209impl<Reply: TermReplySender + Clone> Screen<Reply> {
1210 pub fn handle_action(&mut self, action: Action) {
1211 match action {
1212 Action::Print(c) => self.text(c),
1213 Action::PrintString(s) => s.chars().for_each(|c| self.text(c)),
1214 Action::Control(code) => self.handle_control(code),
1215 Action::DeviceControl(mode) => self.handle_device_control(mode),
1216 Action::OperatingSystemCommand(cmd) => self.handle_os_command(*cmd),
1217 Action::CSI(csi) => self.handle_csi(csi),
1218 Action::Esc(esc) => self.handle_esc(esc),
1219 Action::Sixel(_) => (),
1220 Action::XtGetTcap(names) => self.handle_xt_get_tcap(names),
1221 Action::KittyImage(_) => (),
1222 }
1223 }
1224
1225 fn handle_control(&mut self, code: ControlCode) {
1226 match code {
1227 ControlCode::Null => {}
1228 ControlCode::StartOfHeading => skip!("StartOfHeading"),
1229 ControlCode::StartOfText => skip!("StartOfText"),
1230 ControlCode::EndOfText => skip!("EndOfText"),
1231 ControlCode::EndOfTransmission => skip!("EndOfTransmission"),
1232 ControlCode::Enquiry => skip!("Enquiry"),
1233 ControlCode::Acknowledge => skip!("Acknowledge"),
1234 ControlCode::Bell => self.bel(),
1235 ControlCode::Backspace => self.grid_mut().col_dec(1),
1236 ControlCode::HorizontalTab => self.tab(),
1237 ControlCode::LineFeed => {
1238 self.grid_mut().row_inc_scroll(1);
1239 }
1240 ControlCode::VerticalTab => {
1241 self.grid_mut().row_inc_scroll(1);
1242 }
1243 ControlCode::FormFeed => {
1244 self.grid_mut().row_inc_scroll(1);
1245 }
1246 ControlCode::CarriageReturn => self.grid_mut().col_set(0),
1247 ControlCode::ShiftOut => self.shift_out = true,
1248 ControlCode::ShiftIn => self.shift_out = false,
1249 ControlCode::DataLinkEscape => skip!("DataLinkEscape"),
1250 ControlCode::DeviceControlOne => skip!("DeviceControlOne"),
1251 ControlCode::DeviceControlTwo => skip!("DeviceControlTwo"),
1252 ControlCode::DeviceControlThree => skip!("DeviceControlThree"),
1253 ControlCode::DeviceControlFour => skip!("DeviceControlFour"),
1254 ControlCode::NegativeAcknowledge => skip!("NegativeAcknowledge"),
1255 ControlCode::SynchronousIdle => skip!("SynchronousIdle"),
1256 ControlCode::EndOfTransmissionBlock => {
1257 skip!("EndOfTransmissionBlock")
1258 }
1259 ControlCode::Cancel => skip!("Cancel"),
1260 ControlCode::EndOfMedium => skip!("EndOfMedium"),
1261 ControlCode::Substitute => skip!("Substitute"),
1262 ControlCode::Escape => skip!("Escape"),
1263 ControlCode::FileSeparator => skip!("FileSeparator"),
1264 ControlCode::GroupSeparator => skip!("GroupSeparator"),
1265 ControlCode::RecordSeparator => skip!("RecordSeparator"),
1266 ControlCode::UnitSeparator => skip!("UnitSeparator"),
1267 ControlCode::BPH => skip!("BPH"),
1268 ControlCode::NBH => skip!("NBH"),
1269 ControlCode::IND => skip!("IND"),
1270 ControlCode::NEL => skip!("NEL"),
1271 ControlCode::SSA => skip!("SSA"),
1272 ControlCode::ESA => skip!("ESA"),
1273 ControlCode::HTS => skip!("HTS"),
1274 ControlCode::HTJ => skip!("HTJ"),
1275 ControlCode::VTS => skip!("VTS"),
1276 ControlCode::PLD => skip!("PLD"),
1277 ControlCode::PLU => skip!("PLU"),
1278 ControlCode::RI => self.ri(),
1279 ControlCode::SS2 => skip!("SS2"),
1280 ControlCode::SS3 => skip!("SS3"),
1281 ControlCode::DCS => skip!("DCS"),
1282 ControlCode::PU1 => skip!("PU1"),
1283 ControlCode::PU2 => skip!("PU2"),
1284 ControlCode::STS => skip!("STS"),
1285 ControlCode::CCH => skip!("CCH"),
1286 ControlCode::MW => skip!("MW"),
1287 ControlCode::SPA => skip!("SPA"),
1288 ControlCode::EPA => skip!("EPA"),
1289 ControlCode::SOS => skip!("SOS"),
1290 ControlCode::SCI => skip!("SCI"),
1291 ControlCode::CSI => skip!("CSI"),
1292 ControlCode::ST => skip!("ST"),
1293 ControlCode::OSC => skip!("OSC"),
1294 ControlCode::PM => skip!("PM"),
1295 ControlCode::APC => skip!("APC"),
1296 }
1297 }
1298
1299 fn handle_device_control(&mut self, _mode: DeviceControlMode) {
1300 skip!("DeviceControl");
1301 }
1302
1303 fn handle_os_command(&mut self, cmd: OperatingSystemCommand) {
1304 match cmd {
1305 OperatingSystemCommand::SetIconNameAndWindowTitle(icon_and_title) => {
1306 self.icon_name.clone_from(&icon_and_title);
1307 self.icon_name = icon_and_title.clone();
1308 self.title = icon_and_title;
1309 }
1310 OperatingSystemCommand::SetWindowTitle(title) => self.title = title,
1311 OperatingSystemCommand::SetWindowTitleSun(_) => {
1312 skip!("SetWindowTitleSun")
1313 }
1314 OperatingSystemCommand::SetIconName(icon) => self.icon_name = icon,
1315 OperatingSystemCommand::SetIconNameSun(_) => skip!("SetIconNameSun"),
1316 OperatingSystemCommand::SetHyperlink(_) => skip!("SetHyperlink"),
1317 OperatingSystemCommand::ClearSelection(_) => skip!("ClearSelection"),
1318 OperatingSystemCommand::QuerySelection(_) => skip!("QuerySelection"),
1319 OperatingSystemCommand::SetSelection(_, _) => skip!("SetSelection"),
1320 OperatingSystemCommand::SystemNotification(_) => {
1321 skip!("SystemNotification")
1322 }
1323 OperatingSystemCommand::ITermProprietary(_) => skip!("ITermProprietary"),
1324 OperatingSystemCommand::FinalTermSemanticPrompt(p) => {
1325 skip!("FinalTermSemanticPrompt {:?}", p)
1326 }
1327 OperatingSystemCommand::ChangeColorNumber(_) => {
1328 skip!("ChangeColorNumber")
1329 }
1330 OperatingSystemCommand::ChangeDynamicColors(first_color, colors) => {
1331 skip!("ChangeDynamicColors {:?} {:?}", first_color, colors)
1332 }
1333 OperatingSystemCommand::ResetDynamicColor(_) => {
1334 skip!("ResetDynamicColor")
1335 }
1336 OperatingSystemCommand::CurrentWorkingDirectory(_) => {
1337 skip!("CurrentWorkingDirectory")
1338 }
1339 OperatingSystemCommand::ResetColors(_) => skip!("ResetColors"),
1340 OperatingSystemCommand::RxvtExtension(_) => skip!("RxvtExtension"),
1341 OperatingSystemCommand::ConEmuProgress(_progress) => {
1342 skip!("ConEmuProgress")
1343 }
1344 OperatingSystemCommand::Unspecified(data) => {
1345 let strings: Vec<_> = data
1346 .into_iter()
1347 .map(|bytes| String::from_utf8_lossy(bytes.as_slice()).to_string())
1348 .collect();
1349 skip!("OSC: Unspecified {:?}", strings);
1350 }
1351 }
1352 }
1353
1354 fn handle_csi(&mut self, csi: CSI) {
1355 match csi {
1356 CSI::Sgr(sgr) => match sgr {
1357 Sgr::Reset => self.attrs = Attrs::default(),
1358 Sgr::Intensity(level) => match level {
1359 termwiz::cell::Intensity::Normal => self.attrs.set_bold(false),
1360 termwiz::cell::Intensity::Bold => self.attrs.set_bold(true),
1361 termwiz::cell::Intensity::Half => self.attrs.set_bold(true),
1362 },
1363 Sgr::Underline(mode) => match mode {
1364 termwiz::cell::Underline::None => self.attrs.set_underline(false),
1365 termwiz::cell::Underline::Single
1366 | termwiz::cell::Underline::Double
1367 | termwiz::cell::Underline::Curly
1368 | termwiz::cell::Underline::Dotted
1369 | termwiz::cell::Underline::Dashed => self.attrs.set_underline(true),
1370 },
1371 Sgr::UnderlineColor(_) => skip!("UnderlineColor"),
1372 Sgr::Blink(_) => skip!("Blink"),
1373 Sgr::Italic(mode) => self.attrs.set_italic(mode),
1374 Sgr::Inverse(mode) => self.attrs.set_inverse(mode),
1375 Sgr::Invisible(_) => skip!("Invisible"),
1376 Sgr::StrikeThrough(_) => skip!("StrikeThrough"),
1377 Sgr::Font(_) => skip!("Font"),
1378 Sgr::Foreground(color) => self.attrs.fgcolor = color.into(),
1379 Sgr::Background(color) => self.attrs.bgcolor = color.into(),
1380 Sgr::Overline(_) => skip!("Overline"),
1381 Sgr::VerticalAlign(_) => skip!("VerticalAlign"),
1382 },
1383 CSI::Cursor(cursor) => match cursor {
1384 Cursor::BackwardTabulation(_) => skip!("BackwardTabulation"),
1385 Cursor::TabulationClear(_) => skip!("TabulationClear"),
1386 Cursor::CharacterAbsolute(pos) => {
1387 self.grid_mut().col_set(pos.as_zero_based() as u16)
1388 }
1389 Cursor::CharacterPositionAbsolute(_) => {
1390 skip!("CharacterPositionAbsolute")
1391 }
1392 Cursor::CharacterPositionBackward(_) => {
1393 skip!("CharacterPositionBackward")
1394 }
1395 Cursor::CharacterPositionForward(_) => {
1396 skip!("CharacterPositionForward")
1397 }
1398 Cursor::CharacterAndLinePosition { line, col } => {
1399 self.grid_mut().set_pos(crate::grid::Pos {
1400 row: line.as_zero_based() as u16,
1401 col: col.as_zero_based() as u16,
1402 });
1403 }
1404 Cursor::LinePositionAbsolute(row) => {
1405 self.grid_mut().row_set((row - 1) as u16)
1406 }
1407 Cursor::LinePositionBackward(_) => skip!("LinePositionBackward"),
1408 Cursor::LinePositionForward(_) => skip!("LinePositionForward"),
1409 Cursor::ForwardTabulation(_) => skip!("ForwardTabulation"),
1410 Cursor::NextLine(_) => skip!("NextLine"),
1411 Cursor::PrecedingLine(_) => skip!("PrecedingLine"),
1412 Cursor::ActivePositionReport { line: _, col: _ } => {
1413 skip!("ActivePositionReport")
1414 }
1415 Cursor::RequestActivePositionReport => {
1416 let pos = self.grid().pos();
1417 let es = CSI::Cursor(Cursor::ActivePositionReport {
1418 line: OneBased::from_zero_based(pos.row.into()),
1419 col: OneBased::from_zero_based(pos.col.into()),
1420 });
1421 self.reply_sender.reply(es.to_compact_string());
1422 }
1423 Cursor::SaveCursor => skip!("SaveCursor"),
1424 Cursor::RestoreCursor => skip!("RestoreCursor"),
1425 Cursor::TabulationControl(_) => skip!("TabulationControl"),
1426 Cursor::Left(count) => self.grid_mut().col_dec(count as u16),
1427 Cursor::Down(count) => self.grid_mut().row_inc_clamp(count as u16),
1428 Cursor::Right(count) => self.grid_mut().col_inc_clamp(count as u16),
1429 Cursor::Position { line, col } => {
1430 self.grid_mut().set_pos(crate::grid::Pos {
1431 row: line.as_zero_based() as u16,
1432 col: col.as_zero_based() as u16,
1433 })
1434 }
1435 Cursor::Up(count) => self.grid_mut().row_dec_clamp(count as u16),
1436 Cursor::LineTabulation(_) => skip!("LineTabulation"),
1437 Cursor::SetTopAndBottomMargins { top, bottom } => {
1438 self.grid_mut().set_scroll_region(
1439 top.as_zero_based() as u16,
1440 bottom.as_zero_based() as u16,
1441 )
1442 }
1443 Cursor::SetLeftAndRightMargins { left: _, right: _ } => {
1444 skip!("SetLeftAndRightMargins")
1445 }
1446 Cursor::CursorStyle(style) => {
1447 self.cursor_style = style;
1448 }
1449 },
1450 CSI::Edit(edit) => match edit {
1451 Edit::DeleteCharacter(count) => {
1452 self.grid_mut().delete_cells(count as u16)
1453 }
1454 Edit::DeleteLine(count) => self.grid_mut().delete_lines(count as u16),
1455 Edit::EraseCharacter(count) => {
1456 let attrs = self.attrs;
1457 self.grid_mut().erase_cells(count as u16, attrs);
1458 }
1459 Edit::EraseInLine(mode) => {
1460 let attrs = self.attrs;
1461 match mode {
1462 EraseInLine::EraseToEndOfLine => {
1463 self.grid_mut().erase_row_forward(attrs)
1464 }
1465 EraseInLine::EraseToStartOfLine => {
1466 self.grid_mut().erase_row_backward(attrs)
1467 }
1468 EraseInLine::EraseLine => self.grid_mut().erase_row(attrs),
1469 }
1470 }
1471 Edit::InsertCharacter(count) => {
1472 self.ich(u16::try_from(count).unwrap_or_default())
1473 }
1474 Edit::InsertLine(count) => self.grid_mut().insert_lines(count as u16),
1475 Edit::ScrollDown(count) => self.grid_mut().scroll_down(count as u16),
1476 Edit::ScrollUp(count) => self.grid_mut().scroll_up(count as u16),
1477 Edit::EraseInDisplay(mode) => {
1478 let attrs = self.attrs;
1479 match mode {
1480 EraseInDisplay::EraseToEndOfDisplay => {
1481 self.grid_mut().erase_all_forward(attrs)
1482 }
1483 EraseInDisplay::EraseToStartOfDisplay => {
1484 self.grid_mut().erase_all_backward(attrs)
1485 }
1486 EraseInDisplay::EraseDisplay => self.grid_mut().erase_all(attrs),
1487 EraseInDisplay::EraseScrollback => skip!("EraseScrollback"),
1488 }
1489 }
1490 Edit::Repeat(_) => skip!("Repeat"),
1491 },
1492 CSI::Mode(mode) => match mode {
1493 termwiz::escape::csi::Mode::SetDecPrivateMode(pmode) => match pmode {
1494 DecPrivateMode::Code(code) => match code {
1495 DecPrivateModeCode::ApplicationCursorKeys => {
1496 self.set_mode(MODE_APPLICATION_CURSOR)
1497 }
1498 DecPrivateModeCode::DecAnsiMode => skip!("DecAnsiMode"),
1499 DecPrivateModeCode::Select132Columns => {
1500 skip!("Select132Columns")
1501 }
1502 DecPrivateModeCode::SmoothScroll => skip!("SmoothScroll"),
1503 DecPrivateModeCode::ReverseVideo => skip!("ReverseVideo"),
1504 DecPrivateModeCode::OriginMode => {
1505 self.grid_mut().set_origin_mode(true)
1506 }
1507 DecPrivateModeCode::AutoWrap => skip!("AutoWrap"),
1508 DecPrivateModeCode::AutoRepeat => skip!("AutoRepeat"),
1509 DecPrivateModeCode::StartBlinkingCursor => {
1510 skip!("StartBlinkingCursor")
1511 }
1512 DecPrivateModeCode::ShowCursor => self.clear_mode(MODE_HIDE_CURSOR),
1513 DecPrivateModeCode::ReverseWraparound => {
1514 skip!("ReverseWraparound")
1515 }
1516 DecPrivateModeCode::LeftRightMarginMode => {
1517 skip!("LeftRightMarginMode")
1518 }
1519 DecPrivateModeCode::SixelDisplayMode => {
1520 skip!("SixelDisplayMode")
1521 }
1522 DecPrivateModeCode::MouseTracking => {
1523 self.set_mouse_mode(MouseProtocolMode::PressRelease)
1524 }
1525 DecPrivateModeCode::HighlightMouseTracking => {
1526 skip!("HighlightMouseTracking")
1527 }
1528 DecPrivateModeCode::ButtonEventMouse => {
1529 self.set_mouse_mode(MouseProtocolMode::ButtonMotion)
1530 }
1531 DecPrivateModeCode::AnyEventMouse => {
1532 self.set_mouse_mode(MouseProtocolMode::AnyMotion)
1533 }
1534 DecPrivateModeCode::FocusTracking => skip!("FocusTracking"),
1535 DecPrivateModeCode::Utf8Mouse => {
1536 self.set_mouse_encoding(MouseProtocolEncoding::Utf8)
1537 }
1538 DecPrivateModeCode::SGRMouse => {
1539 self.set_mouse_encoding(MouseProtocolEncoding::Sgr)
1540 }
1541 DecPrivateModeCode::SGRPixelsMouse => skip!("SGRPixelsMouse"),
1542 DecPrivateModeCode::XTermMetaSendsEscape => {
1543 skip!("XTermMetaSendsEscape")
1544 }
1545 DecPrivateModeCode::XTermAltSendsEscape => {
1546 skip!("XTermAltSendsEscape")
1547 }
1548 DecPrivateModeCode::SaveCursor => skip!("SaveCursor"),
1549 DecPrivateModeCode::ClearAndEnableAlternateScreen => {
1550 self.decsc();
1551 self.alternate_grid.clear();
1552 self.enter_alternate_grid();
1553 }
1554 DecPrivateModeCode::EnableAlternateScreen => {
1555 self.enter_alternate_grid();
1556 }
1557 DecPrivateModeCode::OptEnableAlternateScreen => {
1558 skip!("OptEnableAlternateScreen")
1559 }
1560 DecPrivateModeCode::BracketedPaste => {
1561 self.set_mode(MODE_BRACKETED_PASTE);
1562 }
1563 DecPrivateModeCode::GraphemeClustering => {
1564 skip!("GraphemeClustering");
1565 }
1566 DecPrivateModeCode::UsePrivateColorRegistersForEachGraphic => {
1567 skip!("UsePrivateColorRegistersForEachGraphic")
1568 }
1569 DecPrivateModeCode::SynchronizedOutput => {
1570 skip!("SynchronizedOutput")
1571 }
1572 DecPrivateModeCode::MinTTYApplicationEscapeKeyMode => {
1573 skip!("MinTTYApplicationEscapeKeyMode")
1574 }
1575 DecPrivateModeCode::SixelScrollsRight => {
1576 skip!("SixelScrollsRight")
1577 }
1578 DecPrivateModeCode::Win32InputMode => skip!("Win32InputMode"),
1579 },
1580 DecPrivateMode::Unspecified(9) => {
1581 self.set_mouse_mode(MouseProtocolMode::Press)
1582 }
1583 DecPrivateMode::Unspecified(m) => {
1584 skip!("SetDecPrivateMode:Unspecified:{}", m)
1585 }
1586 },
1587 termwiz::escape::csi::Mode::ResetDecPrivateMode(pmode) => match pmode {
1588 DecPrivateMode::Code(code) => match code {
1589 DecPrivateModeCode::ApplicationCursorKeys => {
1590 self.clear_mode(MODE_APPLICATION_CURSOR)
1591 }
1592 DecPrivateModeCode::DecAnsiMode => skip!("DecAnsiMode"),
1593 DecPrivateModeCode::Select132Columns => {
1594 skip!("Select132Columns")
1595 }
1596 DecPrivateModeCode::SmoothScroll => skip!("SmoothScroll"),
1597 DecPrivateModeCode::ReverseVideo => skip!("ReverseVideo"),
1598 DecPrivateModeCode::OriginMode => {
1599 self.grid_mut().set_origin_mode(false)
1600 }
1601 DecPrivateModeCode::AutoWrap => skip!("AutoWrap"),
1602 DecPrivateModeCode::AutoRepeat => skip!("AutoRepeat"),
1603 DecPrivateModeCode::StartBlinkingCursor => {
1604 skip!("StartBlinkingCursor")
1605 }
1606 DecPrivateModeCode::ShowCursor => self.set_mode(MODE_HIDE_CURSOR),
1607 DecPrivateModeCode::ReverseWraparound => {
1608 skip!("ReverseWraparound")
1609 }
1610 DecPrivateModeCode::LeftRightMarginMode => {
1611 skip!("LeftRightMarginMode")
1612 }
1613 DecPrivateModeCode::SixelDisplayMode => {
1614 skip!("SixelDisplayMode")
1615 }
1616 DecPrivateModeCode::MouseTracking => {
1617 self.clear_mouse_mode(MouseProtocolMode::PressRelease)
1618 }
1619 DecPrivateModeCode::HighlightMouseTracking => {
1620 skip!("HighlightMouseTracking")
1621 }
1622 DecPrivateModeCode::ButtonEventMouse => {
1623 self.clear_mouse_mode(MouseProtocolMode::ButtonMotion)
1624 }
1625 DecPrivateModeCode::AnyEventMouse => {
1626 self.clear_mouse_mode(MouseProtocolMode::AnyMotion)
1627 }
1628 DecPrivateModeCode::FocusTracking => skip!("FocusTracking"),
1629 DecPrivateModeCode::Utf8Mouse => {
1630 self.clear_mouse_encoding(MouseProtocolEncoding::Utf8)
1631 }
1632 DecPrivateModeCode::SGRMouse => {
1633 self.clear_mouse_encoding(MouseProtocolEncoding::Sgr)
1634 }
1635 DecPrivateModeCode::SGRPixelsMouse => {
1636 skip!("SGRPixelsMouse")
1637 }
1638 DecPrivateModeCode::XTermMetaSendsEscape => {
1639 skip!("XTermMetaSendsEscape")
1640 }
1641 DecPrivateModeCode::XTermAltSendsEscape => {
1642 skip!("XTermAltSendsEscape")
1643 }
1644 DecPrivateModeCode::SaveCursor => skip!("SaveCursor"),
1645 DecPrivateModeCode::ClearAndEnableAlternateScreen => {
1646 self.exit_alternate_grid();
1647 self.decrc();
1648 }
1649 DecPrivateModeCode::EnableAlternateScreen => {
1650 self.exit_alternate_grid()
1651 }
1652 DecPrivateModeCode::OptEnableAlternateScreen => {
1653 skip!("OptEnableAlternateScreen")
1654 }
1655 DecPrivateModeCode::BracketedPaste => {
1656 self.clear_mode(MODE_BRACKETED_PASTE)
1657 }
1658 DecPrivateModeCode::GraphemeClustering => {
1659 skip!("GraphemeClustering");
1660 }
1661 DecPrivateModeCode::UsePrivateColorRegistersForEachGraphic => {
1662 skip!("UsePrivateColorRegistersForEachGraphic")
1663 }
1664 DecPrivateModeCode::SynchronizedOutput => {
1665 skip!("SynchronizedOutput")
1666 }
1667 DecPrivateModeCode::MinTTYApplicationEscapeKeyMode => {
1668 skip!("MinTTYApplicationEscapeKeyMode")
1669 }
1670 DecPrivateModeCode::SixelScrollsRight => {
1671 skip!("SixelScrollsRight")
1672 }
1673 DecPrivateModeCode::Win32InputMode => {
1674 skip!("Win32InputMode")
1675 }
1676 },
1677 DecPrivateMode::Unspecified(9) => {
1678 self.clear_mouse_mode(MouseProtocolMode::Press)
1679 }
1680 termwiz::escape::csi::DecPrivateMode::Unspecified(_) => {
1681 skip!("DecPrivateMode::Unspecified")
1682 }
1683 },
1684 termwiz::escape::csi::Mode::SaveDecPrivateMode(pmode) => match pmode {
1685 DecPrivateMode::Code(code) => match code {
1686 DecPrivateModeCode::ApplicationCursorKeys => {
1687 skip!("ApplicationCursorKeys")
1688 }
1689 DecPrivateModeCode::DecAnsiMode => skip!("DecAnsiMode"),
1690 DecPrivateModeCode::Select132Columns => {
1691 skip!("Select132Columns")
1692 }
1693 DecPrivateModeCode::SmoothScroll => skip!("SmoothScroll"),
1694 DecPrivateModeCode::ReverseVideo => skip!("ReverseVideo"),
1695 DecPrivateModeCode::OriginMode => skip!("OriginMode"),
1696 DecPrivateModeCode::AutoWrap => skip!("AutoWrap"),
1697 DecPrivateModeCode::AutoRepeat => skip!("AutoRepeat"),
1698 DecPrivateModeCode::StartBlinkingCursor => {
1699 skip!("StartBlinkingCursor")
1700 }
1701 DecPrivateModeCode::ShowCursor => skip!("ShowCursor"),
1702 DecPrivateModeCode::ReverseWraparound => {
1703 skip!("ReverseWraparound")
1704 }
1705 DecPrivateModeCode::LeftRightMarginMode => {
1706 skip!("LeftRightMarginMode")
1707 }
1708 DecPrivateModeCode::SixelDisplayMode => {
1709 skip!("SixelDisplayMode")
1710 }
1711 DecPrivateModeCode::MouseTracking => skip!("MouseTracking"),
1712 DecPrivateModeCode::HighlightMouseTracking => {
1713 skip!("HighlightMouseTracking")
1714 }
1715 DecPrivateModeCode::ButtonEventMouse => {
1716 skip!("ButtonEventMouse")
1717 }
1718 DecPrivateModeCode::AnyEventMouse => skip!("AnyEventMouse"),
1719 DecPrivateModeCode::FocusTracking => skip!("FocusTracking"),
1720 DecPrivateModeCode::Utf8Mouse => skip!("Utf8Mouse"),
1721 DecPrivateModeCode::SGRMouse => skip!("SGRMouse"),
1722 DecPrivateModeCode::SGRPixelsMouse => {
1723 skip!("SGRPixelsMouse")
1724 }
1725 DecPrivateModeCode::XTermMetaSendsEscape => {
1726 skip!("XTermMetaSendsEscape")
1727 }
1728 DecPrivateModeCode::XTermAltSendsEscape => {
1729 skip!("XTermAltSendsEscape")
1730 }
1731 DecPrivateModeCode::SaveCursor => skip!("SaveCursor"),
1732 DecPrivateModeCode::ClearAndEnableAlternateScreen => {
1733 skip!("ClearAndEnableAlternateScreen")
1734 }
1735 DecPrivateModeCode::EnableAlternateScreen => {
1736 skip!("EnableAlternateScreen")
1737 }
1738 DecPrivateModeCode::OptEnableAlternateScreen => {
1739 skip!("OptEnableAlternateScreen")
1740 }
1741 DecPrivateModeCode::BracketedPaste => {
1742 skip!("BracketedPaste")
1743 }
1744 DecPrivateModeCode::GraphemeClustering => {
1745 skip!("GraphemeClustering");
1746 }
1747 DecPrivateModeCode::UsePrivateColorRegistersForEachGraphic => {
1748 skip!("UsePrivateColorRegistersForEachGraphic")
1749 }
1750 DecPrivateModeCode::SynchronizedOutput => {
1751 skip!("SynchronizedOutput")
1752 }
1753 DecPrivateModeCode::MinTTYApplicationEscapeKeyMode => {
1754 skip!("MinTTYApplicationEscapeKeyMode")
1755 }
1756 DecPrivateModeCode::SixelScrollsRight => {
1757 skip!("SixelScrollsRight")
1758 }
1759 DecPrivateModeCode::Win32InputMode => {
1760 skip!("Win32InputMode")
1761 }
1762 },
1763 termwiz::escape::csi::DecPrivateMode::Unspecified(_) => todo!(),
1764 },
1765 termwiz::escape::csi::Mode::RestoreDecPrivateMode(_) => {
1766 skip!("RestoreDecPrivateMode")
1767 }
1768 termwiz::escape::csi::Mode::QueryDecPrivateMode(_) => {
1769 skip!("QueryDecPrivateMode")
1770 }
1771 termwiz::escape::csi::Mode::SetMode(mode) => match mode {
1772 TerminalMode::Code(code) => match code {
1773 TerminalModeCode::KeyboardAction => {
1774 skip!("TerminalModeCode::KeyboardAction")
1775 }
1776 TerminalModeCode::Insert => skip!("TerminalModeCode::Insert"),
1777 TerminalModeCode::BiDirectionalSupportMode => {
1778 skip!("TerminalModeCode::BiDirectionalSupportMode")
1779 }
1780 TerminalModeCode::SendReceive => {
1781 skip!("TerminalModeCode::SendReceive")
1782 }
1783 TerminalModeCode::AutomaticNewline => {
1784 skip!("TerminalModeCode::AutomaticNewline")
1785 }
1786 TerminalModeCode::ShowCursor => {
1787 skip!("TerminalModeCode::ShowCursor")
1788 }
1789 },
1790 TerminalMode::Unspecified(n) => {
1791 skip!("SetMode -> TerminalMode::Unspecified({})", n)
1792 }
1793 },
1794 termwiz::escape::csi::Mode::ResetMode(mode) => match mode {
1795 TerminalMode::Code(code) => match code {
1796 TerminalModeCode::KeyboardAction => {
1797 skip!("TerminalModeCode::KeyboardAction")
1798 }
1799 TerminalModeCode::Insert => self.insert = false,
1800 TerminalModeCode::BiDirectionalSupportMode => {
1801 skip!("TerminalModeCode::BiDirectionalSupportMode")
1802 }
1803 TerminalModeCode::SendReceive => {
1804 skip!("TerminalModeCode::SendReceive")
1805 }
1806 TerminalModeCode::AutomaticNewline => {
1807 skip!("TerminalModeCode::AutomaticNewline")
1808 }
1809 TerminalModeCode::ShowCursor => {
1810 skip!("TerminalModeCode::ShowCursor")
1811 }
1812 },
1813 TerminalMode::Unspecified(n) => {
1814 skip!("ResetMode -> TerminalMode::Unspecified({})", n)
1815 }
1816 },
1817 termwiz::escape::csi::Mode::QueryMode(_) => skip!("QueryMode"),
1818 termwiz::escape::csi::Mode::XtermKeyMode {
1819 resource: _,
1820 value: _,
1821 } => {
1822 skip!("XtermKeyMode")
1823 }
1824 },
1825 CSI::Device(device) => skip!("Device: {:?}", device),
1826 CSI::Mouse(mouse) => skip!("Mouse: {:?}", mouse),
1827 CSI::Window(win) => match *win {
1828 Window::DeIconify => skip!("DeIconify"),
1829 Window::Iconify => skip!("Iconify"),
1830 Window::MoveWindow { x: _, y: _ } => skip!("MoveWindow"),
1831 Window::ResizeWindowPixels {
1832 width: _,
1833 height: _,
1834 } => {
1835 skip!("ResizeWindowPixels")
1836 }
1837 Window::RaiseWindow => skip!("RaiseWindow"),
1838 Window::LowerWindow => skip!("LowerWindow"),
1839 Window::RefreshWindow => skip!("RefreshWindow"),
1840 Window::ResizeWindowCells {
1841 width: _,
1842 height: _,
1843 } => {
1844 skip!("ResizeWindowCells")
1845 }
1846 Window::RestoreMaximizedWindow => skip!("RestoreMaximizedWindow"),
1847 Window::MaximizeWindow => skip!("MaximizeWindow"),
1848 Window::MaximizeWindowVertically => {
1849 skip!("MaximizeWindowVertically")
1850 }
1851 Window::MaximizeWindowHorizontally => {
1852 skip!("MaximizeWindowHorizontally")
1853 }
1854 Window::UndoFullScreenMode => skip!("UndoFullScreenMode"),
1855 Window::ChangeToFullScreenMode => skip!("ChangeToFullScreenMode"),
1856 Window::ToggleFullScreen => skip!("ToggleFullScreen"),
1857 Window::ReportWindowState => skip!("ReportWindowState"),
1858 Window::ReportWindowPosition => skip!("ReportWindowPosition"),
1859 Window::ReportTextAreaPosition => skip!("ReportTextAreaPosition"),
1860 Window::ReportTextAreaSizePixels => {
1861 skip!("ReportTextAreaSizePixels")
1862 }
1863 Window::ReportWindowSizePixels => skip!("ReportWindowSizePixels"),
1864 Window::ReportScreenSizePixels => skip!("ReportScreenSizePixels"),
1865 Window::ReportCellSizePixels => skip!("ReportCellSizePixels"),
1866 Window::ReportCellSizePixelsResponse {
1867 width: _,
1868 height: _,
1869 } => {
1870 skip!("ReportCellSizePixelsResponse")
1871 }
1872 Window::ReportTextAreaSizeCells => {
1873 skip!("ReportTextAreaSizeCells")
1874 }
1875 Window::ReportScreenSizeCells => skip!("ReportScreenSizeCells"),
1876 Window::ReportIconLabel => skip!("ReportIconLabel"),
1877 Window::ReportWindowTitle => skip!("ReportWindowTitle"),
1878 Window::PushIconAndWindowTitle => skip!("PushIconAndWindowTitle"),
1879 Window::PushIconTitle => skip!("PushIconTitle"),
1880 Window::PushWindowTitle => skip!("PushWindowTitle"),
1881 Window::PopIconAndWindowTitle => skip!("PopIconAndWindowTitle"),
1882 Window::PopIconTitle => skip!("PopIconTitle"),
1883 Window::PopWindowTitle => skip!("PopWindowTitle"),
1884 Window::ChecksumRectangularArea {
1885 request_id: _,
1886 page_number: _,
1887 top: _,
1888 left: _,
1889 bottom: _,
1890 right: _,
1891 } => skip!("ChecksumRectangularArea"),
1892 },
1893 CSI::Keyboard(kb) => match kb {
1894 termwiz::escape::csi::Keyboard::SetKittyState { flags: _, mode: _ } => {
1895 skip!("SetKittyState")
1896 }
1897 termwiz::escape::csi::Keyboard::PushKittyState {
1898 flags: _,
1899 mode: _,
1900 } => {
1901 skip!("PushKittyState")
1902 }
1903 termwiz::escape::csi::Keyboard::PopKittyState(_) => {
1904 skip!("PopKittyState")
1905 }
1906 termwiz::escape::csi::Keyboard::QueryKittySupport => {
1907 skip!("QueryKittySupport")
1908 }
1909 termwiz::escape::csi::Keyboard::ReportKittyState(_) => {
1910 skip!("ReportKittyState")
1911 }
1912 },
1913 CSI::SelectCharacterPath(_, _) => skip!("SelectCharacterPath"),
1914 CSI::Unspecified(n) => {
1915 let handled = match (n.control, n.params.as_slice()) {
1916 ('J', [CsiParam::P(b'?')]) => {
1917 self.decsed(0);
1918 true
1919 }
1920 ('J', [CsiParam::P(b'?'), CsiParam::Integer(mode)]) => {
1921 self.decsed(u16::try_from(*mode).unwrap_or_default());
1922 true
1923 }
1924 ('K', [CsiParam::P(b'?')]) => {
1925 self.decsel(0);
1926 true
1927 }
1928 ('K', [CsiParam::P(b'?'), CsiParam::Integer(mode)]) => {
1929 self.decsel(u16::try_from(*mode).unwrap_or_default());
1930 true
1931 }
1932 _ => false,
1933 };
1934 if !handled {
1935 skip!("unspecified {}", n);
1936 }
1937 }
1938 }
1939 }
1940
1941 fn handle_esc(&mut self, esc: Esc) {
1942 match esc {
1943 Esc::Code(code) => match code {
1944 EscCode::FullReset => self.ris(),
1945 EscCode::Index => skip!("Index"),
1946 EscCode::NextLine => skip!("NextLine"),
1947 EscCode::CursorPositionLowerLeft => {
1948 skip!("CursorPositionLowerLeft")
1949 }
1950 EscCode::HorizontalTabSet => skip!("HorizontalTabSet"),
1951 EscCode::ReverseIndex => self.ri(),
1952 EscCode::SingleShiftG2 => skip!("SingleShiftG2"),
1953 EscCode::SingleShiftG3 => skip!("SingleShiftG3"),
1954 EscCode::StartOfGuardedArea => skip!("StartOfGuardedArea"),
1955 EscCode::EndOfGuardedArea => skip!("EndOfGuardedArea"),
1956 EscCode::StartOfString => skip!("StartOfString"),
1957 EscCode::ReturnTerminalId => skip!("ReturnTerminalId"),
1958 EscCode::StringTerminator => skip!("StringTerminator"),
1959 EscCode::PrivacyMessage => skip!("PrivacyMessage"),
1960 EscCode::ApplicationProgramCommand => {
1961 skip!("ApplicationProgramCommand")
1962 }
1963 EscCode::TmuxTitle => skip!("TmuxTitle"),
1964 EscCode::DecBackIndex => skip!("DecBackIndex"),
1965 EscCode::DecSaveCursorPosition => self.save_cursor(),
1966 EscCode::DecRestoreCursorPosition => self.restore_cursor(),
1967 EscCode::DecApplicationKeyPad => self.deckpam(),
1968 EscCode::DecNormalKeyPad => self.clear_mode(MODE_APPLICATION_KEYPAD),
1969 EscCode::DecLineDrawingG0 => self.g0 = CharSet::DecLineDrawing,
1970 EscCode::UkCharacterSetG0 => self.g0 = CharSet::Uk,
1971 EscCode::AsciiCharacterSetG0 => self.g0 = CharSet::Ascii,
1972 EscCode::DecLineDrawingG1 => self.g1 = CharSet::DecLineDrawing,
1973 EscCode::UkCharacterSetG1 => self.g1 = CharSet::Uk,
1974 EscCode::AsciiCharacterSetG1 => self.g1 = CharSet::Ascii,
1975 EscCode::DecScreenAlignmentDisplay => {
1976 skip!("DecScreenAlignmentDisplay")
1977 }
1978 EscCode::DecDoubleHeightTopHalfLine => {
1979 skip!("DecDoubleHeightTopHalfLine")
1980 }
1981 EscCode::DecDoubleHeightBottomHalfLine => {
1982 skip!("DecDoubleHeightBottomHalfLine")
1983 }
1984 EscCode::DecSingleWidthLine => skip!("DecSingleWidthLine"),
1985 EscCode::DecDoubleWidthLine => skip!("DecDoubleWidthLine"),
1986 EscCode::ApplicationModeArrowUpPress => {
1987 skip!("ApplicationModeArrowUpPress")
1988 }
1989 EscCode::ApplicationModeArrowDownPress => {
1990 skip!("ApplicationModeArrowDownPress")
1991 }
1992 EscCode::ApplicationModeArrowRightPress => {
1993 skip!("ApplicationModeArrowRightPress")
1994 }
1995 EscCode::ApplicationModeArrowLeftPress => {
1996 skip!("ApplicationModeArrowLeftPress")
1997 }
1998 EscCode::ApplicationModeHomePress => {
1999 skip!("ApplicationModeHomePress")
2000 }
2001 EscCode::ApplicationModeEndPress => {
2002 skip!("ApplicationModeEndPress")
2003 }
2004 EscCode::F1Press => skip!("F1Press"),
2005 EscCode::F2Press => skip!("F2Press"),
2006 EscCode::F3Press => skip!("F3Press"),
2007 EscCode::F4Press => skip!("F4Press"),
2008 },
2009 Esc::Unspecified {
2010 intermediate,
2011 control,
2012 } => match (intermediate, control) {
2013 (None, b'g') => self.vb(),
2014 _ => {
2015 skip!("Unspecified esc: {:?} {}", intermediate, control);
2016 }
2017 },
2018 }
2019 }
2020
2021 fn handle_xt_get_tcap(&mut self, _names: Vec<String>) {
2022 skip!("XtGetTcap");
2023 }
2024}