1use bitflags::bitflags;
10
11bitflags! {
12 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
14 pub struct DecModes: u32 {
15 const APPLICATION_CURSOR = 1 << 0;
17 const ORIGIN = 1 << 1;
19 const AUTOWRAP = 1 << 2;
21 const CURSOR_VISIBLE = 1 << 3;
23 const MOUSE_BUTTON = 1 << 4;
25 const MOUSE_CELL_MOTION = 1 << 5;
27 const MOUSE_ALL_MOTION = 1 << 6;
29 const FOCUS_EVENTS = 1 << 7;
31 const MOUSE_SGR = 1 << 8;
33 const ALT_SCREEN = 1 << 9;
35 const BRACKETED_PASTE = 1 << 10;
37 const SYNC_OUTPUT = 1 << 11;
39 }
40}
41
42bitflags! {
43 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
45 pub struct AnsiModes: u8 {
46 const INSERT = 1 << 0;
48 const LINEFEED_NEWLINE = 1 << 1;
50 }
51}
52
53#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
55pub struct Modes {
56 pub dec: DecModes,
57 pub ansi: AnsiModes,
58}
59
60impl Modes {
61 #[must_use]
64 pub fn new() -> Self {
65 Self {
66 dec: DecModes::AUTOWRAP | DecModes::CURSOR_VISIBLE,
67 ansi: AnsiModes::empty(),
68 }
69 }
70
71 pub fn reset(&mut self) {
73 *self = Self::new();
74 }
75
76 #[must_use]
80 pub fn dec_flags(&self) -> DecModes {
81 self.dec
82 }
83
84 #[must_use]
86 pub fn origin_mode(&self) -> bool {
87 self.dec.contains(DecModes::ORIGIN)
88 }
89
90 pub fn set_origin_mode(&mut self, enabled: bool) {
92 self.dec.set(DecModes::ORIGIN, enabled);
93 }
94
95 #[must_use]
97 pub fn autowrap(&self) -> bool {
98 self.dec.contains(DecModes::AUTOWRAP)
99 }
100
101 pub fn set_autowrap(&mut self, enabled: bool) {
103 self.dec.set(DecModes::AUTOWRAP, enabled);
104 }
105
106 #[must_use]
108 pub fn cursor_visible(&self) -> bool {
109 self.dec.contains(DecModes::CURSOR_VISIBLE)
110 }
111
112 pub fn set_cursor_visible(&mut self, enabled: bool) {
114 self.dec.set(DecModes::CURSOR_VISIBLE, enabled);
115 }
116
117 #[must_use]
119 pub fn insert_mode(&self) -> bool {
120 self.ansi.contains(AnsiModes::INSERT)
121 }
122
123 pub fn set_insert_mode(&mut self, enabled: bool) {
125 self.ansi.set(AnsiModes::INSERT, enabled);
126 }
127
128 #[must_use]
130 pub fn alt_screen(&self) -> bool {
131 self.dec.contains(DecModes::ALT_SCREEN)
132 }
133
134 pub fn set_alt_screen(&mut self, enabled: bool) {
136 self.dec.set(DecModes::ALT_SCREEN, enabled);
137 }
138
139 #[must_use]
141 pub fn bracketed_paste(&self) -> bool {
142 self.dec.contains(DecModes::BRACKETED_PASTE)
143 }
144
145 pub fn set_bracketed_paste(&mut self, enabled: bool) {
147 self.dec.set(DecModes::BRACKETED_PASTE, enabled);
148 }
149
150 #[must_use]
152 pub fn focus_events(&self) -> bool {
153 self.dec.contains(DecModes::FOCUS_EVENTS)
154 }
155
156 pub fn set_focus_events(&mut self, enabled: bool) {
158 self.dec.set(DecModes::FOCUS_EVENTS, enabled);
159 }
160
161 #[must_use]
163 pub fn sync_output(&self) -> bool {
164 self.dec.contains(DecModes::SYNC_OUTPUT)
165 }
166
167 pub fn set_sync_output(&mut self, enabled: bool) {
169 self.dec.set(DecModes::SYNC_OUTPUT, enabled);
170 }
171
172 pub fn set_dec_mode(&mut self, mode: u16, enabled: bool) -> bool {
177 let Some(flag) = Self::dec_flag_for_mode(mode) else {
178 return false;
179 };
180 self.dec.set(flag, enabled);
181 true
182 }
183
184 #[must_use]
191 pub fn dec_mode(&self, mode: u16) -> Option<bool> {
192 let flag = Self::dec_flag_for_mode(mode)?;
193 Some(self.dec.contains(flag))
194 }
195
196 pub fn set_ansi_mode(&mut self, mode: u16, enabled: bool) -> bool {
199 let Some(flag) = Self::ansi_flag_for_mode(mode) else {
200 return false;
201 };
202 self.ansi.set(flag, enabled);
203 true
204 }
205
206 fn dec_flag_for_mode(mode: u16) -> Option<DecModes> {
207 let flag = match mode {
208 1 => DecModes::APPLICATION_CURSOR,
209 6 => DecModes::ORIGIN,
210 7 => DecModes::AUTOWRAP,
211 25 => DecModes::CURSOR_VISIBLE,
212 1000 => DecModes::MOUSE_BUTTON,
213 1002 => DecModes::MOUSE_CELL_MOTION,
214 1003 => DecModes::MOUSE_ALL_MOTION,
215 1004 => DecModes::FOCUS_EVENTS,
216 1006 => DecModes::MOUSE_SGR,
217 1049 => DecModes::ALT_SCREEN,
218 2004 => DecModes::BRACKETED_PASTE,
219 2026 => DecModes::SYNC_OUTPUT,
220 _ => return None,
221 };
222 Some(flag)
223 }
224
225 fn ansi_flag_for_mode(mode: u16) -> Option<AnsiModes> {
226 let flag = match mode {
227 4 => AnsiModes::INSERT,
228 20 => AnsiModes::LINEFEED_NEWLINE,
229 _ => return None,
230 };
231 Some(flag)
232 }
233}
234
235#[cfg(test)]
236mod tests {
237 use super::*;
238
239 #[test]
240 fn defaults_have_autowrap_and_cursor_visible() {
241 let m = Modes::new();
242 assert!(m.autowrap());
243 assert!(m.cursor_visible());
244 assert!(!m.origin_mode());
245 assert!(!m.insert_mode());
246 assert!(!m.alt_screen());
247 assert!(!m.bracketed_paste());
248 }
249
250 #[test]
251 fn reset_restores_defaults() {
252 let mut m = Modes::new();
253 m.set_alt_screen(true);
254 m.set_insert_mode(true);
255 m.set_origin_mode(true);
256 m.reset();
257 assert!(m.autowrap());
258 assert!(m.cursor_visible());
259 assert!(!m.alt_screen());
260 assert!(!m.insert_mode());
261 assert!(!m.origin_mode());
262 }
263
264 #[test]
265 fn toggle_origin_mode() {
266 let mut m = Modes::new();
267 m.set_origin_mode(true);
268 assert!(m.origin_mode());
269 m.set_origin_mode(false);
270 assert!(!m.origin_mode());
271 }
272
273 #[test]
274 fn set_dec_mode_by_number() {
275 let mut m = Modes::new();
276 assert!(m.set_dec_mode(25, false));
277 assert!(!m.cursor_visible());
278 assert!(m.set_dec_mode(25, true));
279 assert!(m.cursor_visible());
280 }
281
282 #[test]
283 fn set_dec_mode_unknown_returns_false() {
284 let mut m = Modes::new();
285 assert!(!m.set_dec_mode(9999, true));
286 }
287
288 #[test]
289 fn dec_mode_by_number_reports_state() {
290 let mut m = Modes::new();
291 assert_eq!(m.dec_mode(7), Some(true));
292 assert_eq!(m.dec_mode(1004), Some(false));
293 assert_eq!(m.dec_mode(9999), None);
294 assert!(m.set_dec_mode(1004, true));
295 assert_eq!(m.dec_mode(1004), Some(true));
296 }
297
298 #[test]
299 fn set_ansi_mode_by_number() {
300 let mut m = Modes::new();
301 assert!(m.set_ansi_mode(4, true));
302 assert!(m.insert_mode());
303 assert!(m.set_ansi_mode(4, false));
304 assert!(!m.insert_mode());
305 }
306
307 #[test]
308 fn mouse_modes() {
309 let mut m = Modes::new();
310 m.set_dec_mode(1000, true);
311 assert!(m.dec.contains(DecModes::MOUSE_BUTTON));
312 m.set_dec_mode(1006, true);
313 assert!(m.dec.contains(DecModes::MOUSE_SGR));
314 }
315
316 #[test]
317 fn alt_screen_and_bracketed_paste() {
318 let mut m = Modes::new();
319 m.set_alt_screen(true);
320 m.set_bracketed_paste(true);
321 assert!(m.alt_screen());
322 assert!(m.bracketed_paste());
323 }
324
325 #[test]
326 fn sync_output() {
327 let mut m = Modes::new();
328 assert!(!m.sync_output());
329 m.set_sync_output(true);
330 assert!(m.sync_output());
331 }
332
333 #[test]
336 fn default_has_all_modes_off() {
337 let m = Modes::default();
338 assert!(!m.autowrap());
339 assert!(!m.cursor_visible());
340 assert!(!m.origin_mode());
341 assert!(!m.alt_screen());
342 assert!(!m.insert_mode());
343 assert!(!m.bracketed_paste());
344 assert!(!m.focus_events());
345 assert!(!m.sync_output());
346 }
347
348 #[test]
349 fn new_differs_from_default() {
350 let d = Modes::default();
351 let n = Modes::new();
352 assert_ne!(d, n);
353 assert!(n.autowrap());
354 assert!(n.cursor_visible());
355 assert!(!d.autowrap());
356 assert!(!d.cursor_visible());
357 }
358
359 #[test]
362 fn dec_mode_all_recognized_numbers() {
363 let recognized = [1, 6, 7, 25, 1000, 1002, 1003, 1004, 1006, 1049, 2004, 2026];
364 let mut m = Modes::default();
365 for &mode in &recognized {
366 assert!(
367 m.set_dec_mode(mode, true),
368 "mode {mode} should be recognized"
369 );
370 assert_eq!(m.dec_mode(mode), Some(true), "mode {mode} should be set");
371 }
372 }
373
374 #[test]
375 fn dec_mode_unrecognized_numbers() {
376 let mut m = Modes::new();
377 for mode in [
378 0,
379 2,
380 5,
381 8,
382 999,
383 1001,
384 1005,
385 1050,
386 2005,
387 2025,
388 2027,
389 u16::MAX,
390 ] {
391 assert!(!m.set_dec_mode(mode, true), "mode {mode} should be unknown");
392 assert_eq!(m.dec_mode(mode), None, "mode {mode} query should be None");
393 }
394 }
395
396 #[test]
399 fn ansi_mode_all_recognized() {
400 let mut m = Modes::default();
401 assert!(m.set_ansi_mode(4, true));
402 assert!(m.insert_mode());
403 assert!(m.set_ansi_mode(20, true));
404 assert!(m.ansi.contains(AnsiModes::LINEFEED_NEWLINE));
405 }
406
407 #[test]
408 fn ansi_mode_unrecognized() {
409 let mut m = Modes::new();
410 assert!(!m.set_ansi_mode(0, true));
411 assert!(!m.set_ansi_mode(1, true));
412 assert!(!m.set_ansi_mode(21, true));
413 assert!(!m.set_ansi_mode(u16::MAX, true));
414 }
415
416 #[test]
419 fn focus_events_toggle() {
420 let mut m = Modes::new();
421 assert!(!m.focus_events());
422 m.set_focus_events(true);
423 assert!(m.focus_events());
424 m.set_focus_events(false);
425 assert!(!m.focus_events());
426 }
427
428 #[test]
429 fn dec_flags_accessor() {
430 let m = Modes::new();
431 let flags = m.dec_flags();
432 assert!(flags.contains(DecModes::AUTOWRAP));
433 assert!(flags.contains(DecModes::CURSOR_VISIBLE));
434 assert!(!flags.contains(DecModes::ORIGIN));
435 }
436
437 #[test]
438 fn autowrap_toggle() {
439 let mut m = Modes::new();
440 assert!(m.autowrap());
441 m.set_autowrap(false);
442 assert!(!m.autowrap());
443 m.set_autowrap(true);
444 assert!(m.autowrap());
445 }
446
447 #[test]
448 fn cursor_visible_toggle() {
449 let mut m = Modes::new();
450 assert!(m.cursor_visible());
451 m.set_cursor_visible(false);
452 assert!(!m.cursor_visible());
453 m.set_cursor_visible(true);
454 assert!(m.cursor_visible());
455 }
456
457 #[test]
458 fn bracketed_paste_toggle() {
459 let mut m = Modes::new();
460 assert!(!m.bracketed_paste());
461 m.set_bracketed_paste(true);
462 assert!(m.bracketed_paste());
463 m.set_bracketed_paste(false);
464 assert!(!m.bracketed_paste());
465 }
466
467 #[test]
468 fn sync_output_toggle() {
469 let mut m = Modes::new();
470 assert!(!m.sync_output());
471 m.set_sync_output(true);
472 assert!(m.sync_output());
473 m.set_sync_output(false);
474 assert!(!m.sync_output());
475 }
476
477 #[test]
480 fn double_set_is_idempotent() {
481 let mut m = Modes::new();
482 m.set_origin_mode(true);
483 m.set_origin_mode(true);
484 assert!(m.origin_mode());
485 }
486
487 #[test]
488 fn double_clear_is_idempotent() {
489 let mut m = Modes::new();
490 m.set_origin_mode(false);
491 m.set_origin_mode(false);
492 assert!(!m.origin_mode());
493 }
494
495 #[test]
498 fn setting_one_dec_mode_does_not_affect_others() {
499 let mut m = Modes::new();
500 let before = m.dec;
501 m.set_focus_events(true);
502 let diff = m.dec ^ before;
504 assert_eq!(diff, DecModes::FOCUS_EVENTS);
505 }
506
507 #[test]
508 fn setting_ansi_mode_does_not_affect_dec() {
509 let mut m = Modes::new();
510 let dec_before = m.dec;
511 m.set_insert_mode(true);
512 assert_eq!(m.dec, dec_before);
513 }
514
515 #[test]
516 fn setting_dec_mode_does_not_affect_ansi() {
517 let mut m = Modes::new();
518 let ansi_before = m.ansi;
519 m.set_alt_screen(true);
520 assert_eq!(m.ansi, ansi_before);
521 }
522
523 #[test]
526 fn all_dec_modes_enabled_simultaneously() {
527 let mut m = Modes::default();
528 for &mode in &[1, 6, 7, 25, 1000, 1002, 1003, 1004, 1006, 1049, 2004, 2026] {
529 m.set_dec_mode(mode, true);
530 }
531 for &mode in &[1, 6, 7, 25, 1000, 1002, 1003, 1004, 1006, 1049, 2004, 2026] {
533 assert_eq!(m.dec_mode(mode), Some(true), "mode {mode} should be on");
534 }
535 }
536
537 #[test]
538 fn all_ansi_modes_enabled() {
539 let mut m = Modes::default();
540 m.set_ansi_mode(4, true);
541 m.set_ansi_mode(20, true);
542 assert!(m.insert_mode());
543 assert!(m.ansi.contains(AnsiModes::LINEFEED_NEWLINE));
544 }
545
546 #[test]
549 fn mouse_modes_are_independent_bits() {
550 let mut m = Modes::new();
551 m.set_dec_mode(1000, true);
552 m.set_dec_mode(1002, true);
553 m.set_dec_mode(1003, true);
554 assert!(m.dec.contains(DecModes::MOUSE_BUTTON));
555 assert!(m.dec.contains(DecModes::MOUSE_CELL_MOTION));
556 assert!(m.dec.contains(DecModes::MOUSE_ALL_MOTION));
557 m.set_dec_mode(1002, false);
559 assert!(m.dec.contains(DecModes::MOUSE_BUTTON));
560 assert!(!m.dec.contains(DecModes::MOUSE_CELL_MOTION));
561 assert!(m.dec.contains(DecModes::MOUSE_ALL_MOTION));
562 }
563
564 #[test]
565 fn reset_from_all_modes_enabled() {
566 let mut m = Modes::default();
567 for &mode in &[1, 6, 7, 25, 1000, 1002, 1003, 1004, 1006, 1049, 2004, 2026] {
568 m.set_dec_mode(mode, true);
569 }
570 m.set_ansi_mode(4, true);
571 m.set_ansi_mode(20, true);
572 m.reset();
573 assert_eq!(m, Modes::new());
575 }
576
577 #[test]
580 fn application_cursor_via_dec_mode() {
581 let mut m = Modes::new();
582 assert_eq!(m.dec_mode(1), Some(false));
583 m.set_dec_mode(1, true);
584 assert!(m.dec.contains(DecModes::APPLICATION_CURSOR));
585 assert_eq!(m.dec_mode(1), Some(true));
586 }
587}