xref: /DragonOS/kernel/src/driver/tty/virtual_terminal/virtual_console.rs (revision 4dd4856f933be0b4624c7f7ffa9e3d0c8c218873) !
1 use core::sync::atomic::{AtomicBool, Ordering};
2 
3 use alloc::{
4     sync::{Arc, Weak},
5     vec::Vec,
6 };
7 use bitmap::{traits::BitMapOps, StaticBitmap};
8 use log::warn;
9 
10 use crate::{
11     driver::{
12         serial::serial8250::send_to_default_serial8250_port,
13         tty::{console::ConsoleSwitch, ConsoleFont, KDMode},
14     },
15     libs::{font::FontDesc, rwlock::RwLock},
16     process::Pid,
17 };
18 
19 use super::{
20     console_map::{TranslationMap, TranslationMapType},
21     vc_manager, Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN,
22     DEFAULT_RED,
23 };
24 
25 pub(super) const NPAR: usize = 16;
26 
27 lazy_static! {
28     /// 是否已经添加了软光标
29     pub(super) static ref SOFTCURSOR_ORIGINAL: RwLock<Option<VcCursor>> = RwLock::new(None);
30 
31 
32 }
33 
34 pub static CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);
35 
36 /// ## 虚拟控制台的信息
37 #[derive(Debug, Clone)]
38 pub struct VirtualConsoleData {
39     pub vc_index: usize,
40     pub state: VirtualConsoleInfo,
41     pub saved_state: VirtualConsoleInfo,
42     /// 最大列数
43     pub cols: usize,
44     /// 最大行数
45     pub rows: usize,
46     // ///  每行的字节数
47     // pub bytes_per_row: usize,
48     /// 扫描行数
49     pub scan_lines: usize,
50     /// 字符单元高度
51     pub cell_height: u32,
52 
53     // /// 实际屏幕地址的开始
54     // pub screen_base: VirtAddr,
55     // /// 实际屏幕的结束
56     // pub scr_end: u64,
57     /// 可见窗口的开始
58     pub visible_origin: usize,
59     /// 滚动窗口的顶部
60     pub top: usize,
61     /// 滚动窗口的底部
62     pub bottom: usize,
63     /// 当前读取位置
64     pub pos: usize,
65 
66     /// 颜色集合
67     pub palette: [Color; 16],
68     /// 默认颜色
69     pub def_color: u8,
70     /// 下划线颜色
71     pub underline_color: u32,
72     /// 斜体颜色
73     pub italic_color: u32,
74     /// 半强度颜色
75     pub half_color: u32,
76 
77     pub mode: KDMode,
78     pub vt_mode: VtModeData,
79 
80     /// 是否启用颜色
81     pub color_mode: bool,
82 
83     // 字符
84     pub hi_font_mask: u16,
85     pub font: ConsoleFont,
86 
87     pub erase_char: u16,
88 
89     pub complement_mask: u16,
90     pub s_complement_mask: u16,
91 
92     pub cursor_blink_ms: u16,
93 
94     pub pid: Option<Pid>,
95     pub index: usize,
96 
97     pub vc_state: VirtualConsoleState,
98 
99     // 一些标志
100     /// 指示是否显示 ASCII 字符小于 32 的控制字符(vc_disp_ctrl)
101     pub display_ctrl: bool,
102     /// 指示是否切换高位(meta)位。Meta 键是一个特殊的按键,用于扩展字符集。
103     pub toggle_meta: bool,
104     /// 表示屏幕模式(vc_decscnm)
105     pub screen_mode: bool,
106     /// 指定光标移动的起始位置,是相对于屏幕的左上角还是相对于当前页的左上角(vc_decom)
107     pub origin_mode: bool,
108     /// 控制光标到达行末时是否自动换行(vc_decawm)
109     pub autowrap: bool,
110     /// 控制光标的可见性(vc_deccm)
111     pub cursor_visible: bool,
112     /// 光标相关
113     pub cursor_type: VcCursor,
114     /// 控制插入或替换模式(vc_decim)
115     pub insert_mode: bool,
116     /// 表示一些私有模式或状态,通常由特定终端实现定义(vc_priv)
117     pub private: Vt102_OP,
118     /// 是否需要进行自动换行
119     pub need_wrap: bool,
120     /// 控制鼠标事件的报告方式
121     pub report_mouse: u8,
122     /// 指示终端是否使用 UTF-8 编码
123     pub utf: bool,
124     /// UTF-8 编码的字符计数,表示还需要多少个字节才能够构建完成
125     pub utf_count: u8,
126     /// UTF-8 编码的字符,表示正在构建的utf字符
127     pub utf_char: u32,
128     /// 构建utf时需要的参数,表示目前接收了多少个字节的数据来构建utf字符
129     pub npar: u32,
130     pub par: [u32; NPAR],
131 
132     /// 字符转换表 用于将输入字符映射到特定的字符
133     pub translate: TranslationMap,
134 
135     pub tab_stop: StaticBitmap<256>,
136 
137     pub attr: u8,
138 
139     /// vc缓冲区
140     pub screen_buf: Vec<u16>,
141 
142     /// 对应的Console Driver funcs
143     driver_funcs: Option<Weak<dyn ConsoleSwitch>>,
144 }
145 
146 impl VirtualConsoleData {
147     #[inline(never)]
new(num: usize) -> Self148     pub fn new(num: usize) -> Self {
149         Self {
150             state: VirtualConsoleInfo::new(0, 0),
151             saved_state: Default::default(),
152             cols: Default::default(),
153             rows: Default::default(),
154             // bytes_per_row: Default::default(),
155             scan_lines: Default::default(),
156             cell_height: Default::default(),
157             // origin: Default::default(),
158             // scr_end: Default::default(),
159             visible_origin: Default::default(),
160             top: Default::default(),
161             bottom: Default::default(),
162             palette: [Default::default(); 16],
163             def_color: Default::default(),
164             underline_color: Default::default(),
165             italic_color: Default::default(),
166             half_color: Default::default(),
167             mode: Default::default(),
168             color_mode: Default::default(),
169             hi_font_mask: Default::default(),
170             erase_char: Default::default(),
171             complement_mask: Default::default(),
172             s_complement_mask: Default::default(),
173             cursor_blink_ms: 200,
174             pos: Default::default(),
175             vt_mode: VtModeData {
176                 mode: VtMode::Auto,
177                 relsig: 0,
178                 acqsig: 0,
179             },
180             pid: None,
181             index: 0,
182             font: Default::default(),
183             vc_state: VirtualConsoleState::ESnormal,
184             display_ctrl: Default::default(),
185             toggle_meta: Default::default(),
186             screen_mode: Default::default(),
187             origin_mode: Default::default(),
188             autowrap: Default::default(),
189             cursor_visible: Default::default(),
190             insert_mode: Default::default(),
191             private: Vt102_OP::Pecma,
192             need_wrap: Default::default(),
193             report_mouse: Default::default(),
194             utf: Default::default(),
195             utf_count: Default::default(),
196             utf_char: Default::default(),
197             translate: TranslationMap::new(TranslationMapType::Lat1),
198             npar: Default::default(),
199             tab_stop: StaticBitmap::new(),
200             par: [0; 16],
201             attr: Default::default(),
202             screen_buf: Default::default(),
203             driver_funcs: None,
204             cursor_type: VcCursor::empty(),
205             vc_index: num,
206         }
207     }
208 
init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool)209     pub fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
210         if let Some(rows) = rows {
211             self.rows = rows;
212         }
213         if let Some(cols) = cols {
214             self.cols = cols;
215         }
216 
217         self.pos = self.cols * self.state.y + self.state.x;
218         // self.bytes_per_row = self.cols << 1;
219 
220         self.def_color = 15; // white
221         self.italic_color = 2; // green
222         self.underline_color = 3; // cyan
223         self.half_color = 0x08; // grey
224 
225         self.screen_buf.resize(self.cols * self.rows, 0);
226         self.reset(clear);
227     }
228 
should_update(&self) -> bool229     pub fn should_update(&self) -> bool {
230         self.is_visible() && !CONSOLE_BLANKED.load(Ordering::SeqCst)
231     }
232 
is_visible(&self) -> bool233     pub fn is_visible(&self) -> bool {
234         if let Some(cur_vc) = vc_manager().current_vc_index() {
235             cur_vc == self.vc_index
236         } else {
237             false
238         }
239     }
240 
driver_funcs(&self) -> Arc<dyn ConsoleSwitch>241     fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> {
242         self.driver_funcs.as_ref().unwrap().upgrade().unwrap()
243     }
244 
set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>)245     pub fn set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>) {
246         self.driver_funcs = Some(func);
247     }
248 
reset(&mut self, do_clear: bool)249     pub(super) fn reset(&mut self, do_clear: bool) {
250         self.mode = KDMode::KdText;
251         // unicode?
252         self.vt_mode.mode = VtMode::Auto;
253         self.vt_mode.acqsig = 0;
254         self.vt_mode.relsig = 0;
255         self.display_ctrl = false;
256         self.toggle_meta = false;
257         self.screen_mode = false;
258         self.origin_mode = false;
259         self.autowrap = true;
260         self.cursor_visible = true;
261         self.insert_mode = false;
262         self.need_wrap = false;
263         self.report_mouse = 0;
264         self.utf_count = 0;
265         self.translate = TranslationMap::new(TranslationMapType::Lat1);
266         self.utf = true;
267         self.pid = None;
268         self.vc_state = VirtualConsoleState::ESnormal;
269         self.reset_palette();
270         // self.cursor_type = VcCursor::CUR_UNDERLINE;
271         self.cursor_type = VcCursor::CUR_BLOCK;
272 
273         self.default_attr();
274         self.update_attr();
275 
276         self.tab_stop.set_all(false);
277 
278         for i in (0..256).step_by(8) {
279             self.tab_stop.set(i, true);
280         }
281 
282         self.state.x = 0;
283         self.state.y = 0;
284         self.pos = 0;
285 
286         if do_clear {
287             self.csi_J(2);
288         }
289     }
290 
reset_palette(&mut self)291     fn reset_palette(&mut self) {
292         for (idx, color) in self.palette.iter_mut().enumerate() {
293             color.red = DEFAULT_RED[idx];
294             color.green = DEFAULT_GREEN[idx];
295             color.blue = DEFAULT_BLUE[idx];
296         }
297 
298         self.set_palette();
299     }
300 
set_palette(&self)301     fn set_palette(&self) {
302         if self.mode != KDMode::KdGraphics {
303             // todo: 通知driver层的Console
304             let _ = self.driver_funcs().con_set_palette(self, COLOR_TABLE);
305         }
306     }
307 
308     /// ## 翻译字符,将字符转换为终端控制符
309     /// ### 参数
310     ///
311     /// ### c: 需要转换的字符
312     ///
313     /// ### 返回值
314     /// ### (转换后的字符:i32,是否需要更多的数据才能进行转换:bool)
translate(&mut self, c: &mut u32) -> (Option<u32>, bool)315     pub fn translate(&mut self, c: &mut u32) -> (Option<u32>, bool) {
316         if self.vc_state != VirtualConsoleState::ESnormal {
317             // 在控制字符状态下不需要翻译
318             return (Some(*c), false);
319         }
320         if self.utf && !self.display_ctrl {
321             // utf模式并且不显示控制字符
322             let (ret, rescan) = self.translate_unicode(*c);
323             if let Some(ret) = ret {
324                 *c = ret;
325             }
326             return (ret, rescan);
327         }
328 
329         return (Some(self.translate_ascii(*c)), false);
330     }
331 
332     /// 该数组包含每个字节序列长度变化的阈值
333     /// 即如果由两个字节组成的unicode字符,则长度应该在UTF8_LENGTH_CHANGES[0] ~ UTF8_LENGTH_CHANGES[1]之间
334     const UTF8_LENGTH_CHANGES: &'static [u32] = &[
335         0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff,
336     ];
337 
338     /// ## 翻译字符,将UTF-8 编码的字符转换为 Unicode 编码
339     /// ### 参数
340     ///
341     /// ### c: 需要转换的字符
342     ///
343     /// ### 返回值
344     /// ### (转换后的字符:i32,是否需要重新传入该字符:bool)
345     ///
346     /// !!! 注意,该函数返回true时,元组的第一个数据是无效数据(未转换完成)
translate_unicode(&mut self, c: u32) -> (Option<u32>, bool)347     fn translate_unicode(&mut self, c: u32) -> (Option<u32>, bool) {
348         // 收到的字符不是首个
349         if (c & 0xc0) == 0x80 {
350             // 已经不需要继续的字符了,说明这个字符是非法的
351             if self.utf_count == 0 {
352                 return (Some(0xfffd), false);
353             }
354 
355             self.utf_char = (self.utf_char << 6) | (c & 0x3f);
356             self.npar += 1;
357 
358             self.utf_count -= 1;
359             if self.utf_count > 0 {
360                 // 表示需要更多字节
361                 return (None, false);
362             }
363 
364             let c = self.utf_char;
365 
366             // 先检查一遍是否合格
367             if c <= Self::UTF8_LENGTH_CHANGES[self.npar as usize - 1]
368                 || c > Self::UTF8_LENGTH_CHANGES[self.npar as usize]
369             {
370                 return (Some(0xfffd), false);
371             }
372 
373             return (Some(Self::sanitize_unicode(c)), false);
374         }
375 
376         // 接收到单个ASCII字符或者一个序列的首字符,且上次的未处理完,则上一个字符视为无效,则需要重新传入该字符处理
377         if self.utf_count > 0 {
378             self.utf_count = 0;
379             return (Some(0xfffd), true);
380         }
381 
382         // ascii
383         if c <= 0x7f {
384             return (Some(c), false);
385         }
386 
387         // 第一个字节
388         self.npar = 0;
389         if (c & 0xe0) == 0xc0 {
390             self.utf_count = 1;
391             self.utf_char = c & 0x1f;
392         } else if (c & 0xf0) == 0xe0 {
393             self.utf_count = 2;
394             self.utf_char = c & 0x0f;
395         } else if (c & 0xf8) == 0xf0 {
396             self.utf_count = 3;
397             self.utf_char = c & 0x07;
398         } else if (c & 0xfc) == 0xf8 {
399             self.utf_count = 4;
400             self.utf_char = c & 0x03;
401         } else if (c & 0xfe) == 0xfc {
402             self.utf_count = 5;
403             self.utf_char = c & 0x01;
404         } else {
405             /* 254 and 255 are invalid */
406             return (Some(0xfffd), false);
407         }
408 
409         (None, false)
410     }
411 
412     /// ## 翻译字符,将字符转换为Ascii
translate_ascii(&self, c: u32) -> u32413     fn translate_ascii(&self, c: u32) -> u32 {
414         let mut c = c;
415         if self.toggle_meta {
416             c |= 0x80;
417         }
418 
419         return self.translate.translate(c) as u32;
420     }
421 
422     /// ## 用于替换无效的 Unicode 代码点(code points)。
423     /// Unicode 代码点的范围是从 U+0000 到 U+10FFFF,
424     /// 但是有一些特殊的代码点是无效的或者保留给特定用途的。
425     /// 这个函数的主要目的是将无效的 Unicode 代码点替换为 U+FFFD,即 Unicode 替代字符。
sanitize_unicode(c: u32) -> u32426     fn sanitize_unicode(c: u32) -> u32 {
427         if (0xd800..=0xdfff).contains(&c) || c == 0xfffe || c == 0xffff {
428             return 0xfffd;
429         }
430         return c;
431     }
432 
433     /// 用于表示小于 32 的字符中,哪些字符对应的位被设置为 1,
434     /// 表示这些字符会触发一些特殊的动作,比如光标移动等。
435     /// 这些字符在 disp_ctrl 模式未开启时不应该被显示为图形符号
436     const CTRL_ACTION: u32 = 0x0d00ff81;
437     /// 用于表示哪些控制字符是始终显示的,即便 disp_ctrl 模式未开启。
438     /// 这些字符对于终端来说是必要的,显示它们是为了保证终端正常工作。
439     /// 这些字符在 disp_ctrl 模式开启或关闭时都应该显示为控制字符。
440     const CTRL_ALWAYS: u32 = 0x0800f501;
441 
442     /// ## 用于判断tc(终端字符)在当前VC下是不是需要显示的控制字符
is_control(&self, tc: u32, c: u32) -> bool443     pub fn is_control(&self, tc: u32, c: u32) -> bool {
444         // 当前vc状态机不在正常状态,即在接收特殊字符的状态,则是控制字符
445         if self.vc_state != VirtualConsoleState::ESnormal {
446             return true;
447         }
448 
449         if tc == 0 {
450             return true;
451         }
452 
453         if c < 32 {
454             if self.display_ctrl {
455                 // 查看在位图中是否有该字符
456                 return Self::CTRL_ALWAYS & (1 << c) != 0;
457             } else {
458                 return self.utf || (Self::CTRL_ACTION & (1 << c) != 0);
459             }
460         }
461 
462         if c == 127 && !self.display_ctrl {
463             return true;
464         }
465 
466         if c == 128 + 27 {
467             return true;
468         }
469 
470         false
471     }
472 
set_cursor(&mut self)473     pub(super) fn set_cursor(&mut self) {
474         if self.mode == KDMode::KdGraphics {
475             return;
476         }
477 
478         if self.cursor_visible {
479             // TODO: 处理选择
480             self.add_softcursor();
481             if self.cursor_type.cursor_size() != VcCursor::CUR_NONE {
482                 self.driver_funcs().con_cursor(self, CursorOperation::Draw);
483             }
484         } else {
485             self.hide_cursor();
486         }
487     }
488 
489     /// ## 添加软光标
add_softcursor(&mut self)490     fn add_softcursor(&mut self) {
491         let mut i = self.screen_buf[self.pos] as u32;
492         let cursor_type = self.cursor_type;
493 
494         if !cursor_type.contains(VcCursor::CUR_SW) {
495             return;
496         }
497 
498         if SOFTCURSOR_ORIGINAL.read_irqsave().is_some() {
499             // 已经设置了软光标
500             return;
501         }
502 
503         let mut soft_cursor_guard = SOFTCURSOR_ORIGINAL.write_irqsave();
504         *soft_cursor_guard = Some(unsafe { VcCursor::from_bits_unchecked(i) });
505 
506         let soft_cursor = soft_cursor_guard.unwrap();
507 
508         i |= cursor_type.cursor_set();
509         i ^= cursor_type.cursor_change();
510         if cursor_type.contains(VcCursor::CUR_ALWAYS_BG)
511             && ((soft_cursor.bits & VcCursor::CUR_BG.bits) == (i & VcCursor::CUR_BG.bits))
512         {
513             i ^= VcCursor::CUR_BG.bits;
514         }
515         if cursor_type.contains(VcCursor::CUR_INVERT_FG_BG)
516             && ((i & VcCursor::CUR_FG.bits) == ((i & VcCursor::CUR_BG.bits) >> 4))
517         {
518             i ^= VcCursor::CUR_FG.bits;
519         }
520 
521         self.screen_buf[self.pos] = i as u16;
522 
523         let _ =
524             self.driver_funcs()
525                 .con_putc(self, i as u16, self.state.y as u32, self.state.x as u32);
526     }
527 
hide_cursor(&mut self)528     pub fn hide_cursor(&mut self) {
529         // TODO: 处理选择
530 
531         self.driver_funcs().con_cursor(self, CursorOperation::Erase);
532         self.hide_softcursor();
533     }
534 
hide_softcursor(&mut self)535     fn hide_softcursor(&mut self) {
536         let softcursor = SOFTCURSOR_ORIGINAL.upgradeable_read_irqsave();
537         if softcursor.is_some() {
538             self.screen_buf[self.pos] = softcursor.unwrap().bits as u16;
539             let _ = self.driver_funcs().con_putc(
540                 self,
541                 softcursor.unwrap().bits as u16,
542                 self.state.y as u32,
543                 self.state.x as u32,
544             );
545 
546             *softcursor.upgrade() = None;
547         }
548     }
549 
gotoxay(&mut self, x: i32, y: i32)550     fn gotoxay(&mut self, x: i32, y: i32) {
551         if self.origin_mode {
552             self.gotoxy(x, self.top as i32 + y);
553         } else {
554             self.gotoxy(x, y)
555         }
556     }
557 
558     // ## 将当前vc的光标移动到目标位置
gotoxy(&mut self, x: i32, y: i32)559     fn gotoxy(&mut self, x: i32, y: i32) {
560         if x < 0 {
561             self.state.x = 0;
562         } else if x as usize >= self.cols {
563             self.state.x = self.cols - 1;
564         } else {
565             self.state.x = x as usize;
566         }
567 
568         let max_y;
569         let min_y;
570         if self.origin_mode {
571             min_y = self.top;
572             max_y = self.bottom - 1;
573         } else {
574             min_y = 0;
575             max_y = self.rows - 1;
576         }
577 
578         if y < min_y as i32 {
579             self.state.y = min_y;
580         } else if y >= max_y as i32 {
581             self.state.y = max_y;
582         } else {
583             self.state.y = y as usize;
584         }
585 
586         self.pos = self.state.y * self.cols + self.state.x;
587         self.need_wrap = false;
588     }
589 
scroll(&mut self, dir: ScrollDir, mut nr: usize)590     fn scroll(&mut self, dir: ScrollDir, mut nr: usize) {
591         // todo: uniscr_srceen
592         if self.top + nr >= self.bottom {
593             // 滚动超过一页,则按一页计算
594             nr = self.bottom - self.top - 1;
595         }
596 
597         if nr < 1 {
598             return;
599         }
600 
601         if self.is_visible()
602             && self
603                 .driver_funcs()
604                 .con_scroll(self, self.top, self.bottom, dir, nr)
605         {
606             // 如果成功
607             return;
608         }
609 
610         // 调整screen_buf
611         let count = nr * self.cols;
612         if dir == ScrollDir::Up {
613             for i in self.screen_buf[0..count].iter_mut() {
614                 *i = self.erase_char;
615             }
616             self.screen_buf.rotate_left(count);
617         } else if dir == ScrollDir::Down {
618             todo!();
619         }
620     }
621 
622     /// ## 退格
backspace(&mut self)623     fn backspace(&mut self) {
624         if self.state.x > 0 {
625             self.pos -= 1;
626             self.state.x -= 1;
627             self.need_wrap = false;
628 
629             // TODO: notify
630         }
631     }
632 
633     /// ## 换行
line_feed(&mut self)634     fn line_feed(&mut self) {
635         if self.state.y + 1 == self.bottom {
636             self.scroll(ScrollDir::Up, 1);
637         } else if self.state.y < self.rows - 1 {
638             self.state.y += 1;
639             self.pos += self.cols;
640         }
641 
642         self.need_wrap = false;
643         // TODO: Notify write
644     }
645 
646     /// ## 回车
carriage_return(&mut self)647     fn carriage_return(&mut self) {
648         // 写入位置回退到该行最前
649         self.pos -= self.state.x;
650         self.need_wrap = false;
651         self.state.x = 0;
652     }
653 
654     /// ## Del
delete(&mut self)655     fn delete(&mut self) {
656         // ignore
657     }
658 
659     /// ## 向上滚动虚拟终端的内容,或者将光标上移一行
reverse_index(&mut self)660     fn reverse_index(&mut self) {
661         if self.state.y == self.top {
662             self.scroll(ScrollDir::Down, 1);
663         } else if self.state.y > 0 {
664             self.state.y -= 1;
665             self.pos -= self.cols;
666         }
667         self.need_wrap = false;
668     }
669 
670     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#restore_cur
restore_cursor(&mut self)671     fn restore_cursor(&mut self) {
672         self.saved_state = self.state.clone();
673 
674         self.gotoxy(self.state.x as i32, self.state.y as i32);
675 
676         // TODO Gx_charset
677 
678         self.update_attr();
679         self.need_wrap = false;
680         todo!()
681     }
682 
683     /// ## 设置当前vt的各项属性
set_mode(&mut self, on_off: bool)684     fn set_mode(&mut self, on_off: bool) {
685         for i in 0..self.npar as usize {
686             if self.private == Vt102_OP::Pdec {
687                 match self.par[i] {
688                     1 => {
689                         todo!("kbd todo");
690                     }
691                     3 => {
692                         todo!("reisze todo");
693                     }
694                     5 => {
695                         todo!("invert_screen todo");
696                     }
697                     6 => {
698                         self.origin_mode = on_off;
699                         if on_off {
700                             self.gotoxy(0, self.top as i32);
701                         } else {
702                             self.gotoxy(0, 0);
703                         }
704                     }
705                     7 => {
706                         self.autowrap = on_off;
707                     }
708                     8 => {
709                         todo!("kbd todo");
710                     }
711                     9 => {
712                         todo!("report mouse todo");
713                     }
714                     25 => {
715                         self.cursor_visible = on_off;
716                     }
717                     1000 => {
718                         todo!("report mouse todo");
719                     }
720                     _ => {}
721                 }
722             } else {
723                 match self.par[i] {
724                     3 => {
725                         self.display_ctrl = on_off;
726                     }
727                     4 => {
728                         self.insert_mode = on_off;
729                     }
730                     20 => {
731                         todo!("kbd todo");
732                     }
733                     _ => {}
734                 }
735             }
736         }
737     }
738 
739     #[inline(never)]
do_getpars(&mut self, c: char)740     fn do_getpars(&mut self, c: char) {
741         if c == ';' && self.npar < (NPAR - 1) as u32 {
742             self.npar += 1;
743             return;
744         }
745 
746         if c.is_ascii_digit() {
747             self.par[self.npar as usize] *= 10;
748             self.par[self.npar as usize] += (c as u8 - b'0') as u32;
749             return;
750         }
751 
752         if c as u8 >= 0x20 && c as u8 <= 0x3f {
753             self.vc_state = VirtualConsoleState::EScsiignore;
754             return;
755         }
756 
757         self.vc_state = VirtualConsoleState::ESnormal;
758 
759         match c {
760             'h' => {
761                 if self.private <= Vt102_OP::Pdec {
762                     self.set_mode(true);
763                 }
764                 return;
765             }
766             'l' => {
767                 if self.private <= Vt102_OP::Pdec {
768                     self.set_mode(false);
769                 }
770                 return;
771             }
772             'c' => {
773                 if self.private == Vt102_OP::Pdec {
774                     if self.par[0] != 0 {
775                         self.cursor_type =
776                             VcCursor::make_cursor(self.par[0], self.par[1], self.par[2])
777                     } else {
778                         self.cursor_type = VcCursor::CUR_UNDERLINE;
779                     }
780                     return;
781                 }
782             }
783             'm' => {
784                 if self.private == Vt102_OP::Pdec {
785                     if self.par[0] != 0 {
786                         self.complement_mask = (self.par[0] << 8 | self.par[1]) as u16;
787                     } else {
788                         self.complement_mask = self.s_complement_mask;
789                     }
790                     return;
791                 }
792             }
793             'n' => {
794                 if self.private == Vt102_OP::Pecma {
795                     if self.par[0] == 5 {
796                         send_to_default_serial8250_port("tty status report todo".as_bytes());
797                         panic!();
798                     } else if self.par[0] == 6 {
799                         send_to_default_serial8250_port("tty cursor report todo".as_bytes());
800                         panic!();
801                     }
802                 }
803                 return;
804             }
805             _ => {}
806         }
807 
808         if self.private != Vt102_OP::Pecma {
809             self.private = Vt102_OP::Pecma;
810             return;
811         }
812 
813         match c {
814             'G' | '`' => {
815                 if self.par[0] != 0 {
816                     self.par[0] -= 1;
817                 }
818                 self.gotoxy(self.par[0] as i32, self.state.y as i32);
819                 return;
820             }
821             'A' => {
822                 if self.par[0] == 0 {
823                     self.par[0] += 1;
824                 }
825                 self.gotoxy(
826                     self.state.x as i32,
827                     (self.state.y - self.par[0] as usize) as i32,
828                 );
829                 return;
830             }
831             'B' | 'e' => {
832                 if self.par[0] == 0 {
833                     self.par[0] += 1;
834                 }
835                 self.gotoxy(
836                     self.state.x as i32,
837                     (self.state.y + self.par[0] as usize) as i32,
838                 );
839                 return;
840             }
841             'C' | 'a' => {
842                 if self.par[0] == 0 {
843                     self.par[0] += 1;
844                 }
845                 self.gotoxy(
846                     (self.state.x + self.par[0] as usize) as i32,
847                     self.state.y as i32,
848                 );
849                 return;
850             }
851             'D' => {
852                 if self.par[0] == 0 {
853                     self.par[0] += 1;
854                 }
855                 self.gotoxy(
856                     self.state.x as i32 - self.par[0] as i32,
857                     self.state.y as i32,
858                 );
859                 return;
860             }
861             'E' => {
862                 if self.par[0] == 0 {
863                     self.par[0] += 1;
864                 }
865                 self.gotoxy(0, (self.state.y + self.par[0] as usize) as i32);
866                 return;
867             }
868             'F' => {
869                 if self.par[0] == 0 {
870                     self.par[0] += 1;
871                 }
872                 self.gotoxy(0, self.state.y as i32 - self.par[0] as i32);
873                 return;
874             }
875             'd' => {
876                 if self.par[0] != 0 {
877                     self.par[0] -= 1;
878                 }
879                 self.gotoxay(self.state.x as i32, self.par[0] as i32);
880                 return;
881             }
882             'H' | 'f' => {
883                 // MOVETO
884                 if self.par[0] != 0 {
885                     self.par[0] -= 1;
886                 }
887                 if self.par[1] != 0 {
888                     self.par[1] -= 1;
889                 }
890                 self.gotoxay(self.par[1] as i32, self.par[0] as i32);
891                 return;
892             }
893             'J' => {
894                 self.csi_J(self.par[0]);
895                 return;
896             }
897             'K' => {
898                 self.csi_K(self.par[0]);
899                 return;
900             }
901             'L' => {
902                 todo!("csi_L todo");
903             }
904             'M' => {
905                 todo!("csi_M todo");
906             }
907             'P' => {
908                 todo!("csi_P todo");
909             }
910 
911             // 非ANSI标准,为ANSI拓展
912             'S' => {
913                 self.scroll(ScrollDir::Up, self.par[0] as usize);
914                 return;
915             }
916 
917             'T' => {
918                 self.scroll(ScrollDir::Down, self.par[0] as usize);
919                 return;
920             }
921 
922             'c' => {
923                 if self.par[0] == 0 {
924                     warn!("respone ID todo");
925                 }
926                 return;
927             }
928             'g' => {
929                 if self.par[0] == 0 && self.state.x < 256 {
930                     self.tab_stop.set(self.state.x, true);
931                 } else if self.par[0] == 3 {
932                     self.tab_stop.set_all(false);
933                 }
934                 return;
935             }
936             'm' => {
937                 self.csi_m();
938                 return;
939             }
940             'q' => {
941                 if self.par[0] < 4 {
942                     todo!("vt set led state todo");
943                 }
944                 return;
945             }
946             'r' => {
947                 if self.par[0] == 0 {
948                     self.par[0] += 1;
949                 }
950                 if self.par[1] == 0 {
951                     self.par[1] = self.rows as u32;
952                 }
953                 if self.par[0] < self.par[1] && self.par[1] <= self.rows as u32 {
954                     self.top = self.par[0] as usize - 1;
955                     self.bottom = self.par[1] as usize;
956                     self.gotoxay(0, 0);
957                 }
958                 return;
959             }
960             's' => {
961                 self.saved_state = self.state.clone();
962                 return;
963             }
964             'u' => {
965                 self.restore_cursor();
966                 return;
967             }
968             '@' => {
969                 todo!("csi_at todo");
970             }
971             ']' => {
972                 todo!("set termial command todo");
973             }
974             _ => {}
975         }
976     }
977 
978     /// ##  处理Control Sequence Introducer(控制序列引导符) m字符
979     #[inline(never)]
csi_m(&mut self)980     fn csi_m(&mut self) {
981         let mut i = 0;
982         loop {
983             if i > self.npar as usize {
984                 break;
985             }
986             match self.par[i] {
987                 0 => {
988                     // 关闭所有属性
989                     self.default_attr();
990                 }
991 
992                 1 => {
993                     // 设置粗体
994                     self.state.intensity = VirtualConsoleIntensity::Bold;
995                 }
996 
997                 2 => {
998                     // 设置半亮度(半明显
999                     self.state.intensity = VirtualConsoleIntensity::HalfBright;
1000                 }
1001 
1002                 3 => {
1003                     // 斜体
1004                     self.state.italic = true;
1005                 }
1006 
1007                 4 | 21 => {
1008                     // 下划线
1009 
1010                     // 21是设置双下划线,但是不支持,就单下划线
1011                     self.state.underline = true;
1012                 }
1013 
1014                 5 => {
1015                     // 设置闪烁
1016                     self.state.blink = true;
1017                 }
1018 
1019                 7 => {
1020                     // 设置反显(前景色与背景色对调)
1021                     self.state.reverse = true;
1022                 }
1023 
1024                 10 => {
1025                     // 选择主要字体
1026                     todo!()
1027                 }
1028 
1029                 11 => {
1030                     // 选择第一个替代字体
1031                     todo!()
1032                 }
1033 
1034                 12 => {
1035                     // 选择第二个替代字体
1036                     todo!()
1037                 }
1038 
1039                 22 => {
1040                     //  关闭粗体和半亮度,恢复正常亮度
1041                     self.state.intensity = VirtualConsoleIntensity::Normal;
1042                 }
1043 
1044                 23 => {
1045                     // 关闭斜体
1046                     self.state.italic = false;
1047                 }
1048 
1049                 24 => {
1050                     // 关闭下划线
1051                     self.state.underline = false;
1052                 }
1053 
1054                 25 => {
1055                     // 关闭字符闪烁
1056                     self.state.blink = false;
1057                 }
1058 
1059                 27 => {
1060                     // 关闭反显
1061                     self.state.reverse = false;
1062                 }
1063 
1064                 38 => {
1065                     // 设置前景色
1066                     let (idx, color) = self.t416_color(i);
1067                     i = idx;
1068                     if let Some(color) = color {
1069                         let mut max = color.red.max(color.green);
1070                         max = max.max(color.blue);
1071 
1072                         let mut hue = 0;
1073                         if color.red > max / 2 {
1074                             hue |= 4;
1075                         }
1076                         if color.green > max / 2 {
1077                             hue |= 2;
1078                         }
1079                         if color.blue > max / 2 {
1080                             hue |= 1;
1081                         }
1082 
1083                         if hue == 7 && max <= 0x55 {
1084                             hue = 0;
1085                             self.state.intensity = VirtualConsoleIntensity::Bold;
1086                         } else if max > 0xaa {
1087                             self.state.intensity = VirtualConsoleIntensity::Bold;
1088                         } else {
1089                             self.state.intensity = VirtualConsoleIntensity::Normal;
1090                         }
1091 
1092                         self.state.color = (self.state.color & 0xf0) | hue;
1093                     }
1094                 }
1095 
1096                 48 => {
1097                     // 设置背景色
1098                     let (idx, color) = self.t416_color(i);
1099                     i = idx;
1100                     if let Some(color) = color {
1101                         self.state.color = (self.state.color & 0x0f)
1102                             | ((color.red as u8 & 0x80) >> 1)
1103                             | ((color.green as u8 & 0x80) >> 2)
1104                             | ((color.blue as u8 & 0x80) >> 3);
1105                     }
1106                 }
1107 
1108                 39 => {
1109                     // 恢复默认前景色
1110                     self.state.color = (self.def_color & 0x0f) | (self.state.color & 0xf0);
1111                 }
1112 
1113                 49 => {
1114                     // 恢复默认背景色
1115                     self.state.color = (self.def_color & 0xf0) | (self.state.color & 0x0f);
1116                 }
1117 
1118                 _ => {
1119                     if self.par[i] >= 90 && self.par[i] <= 107 {
1120                         if self.par[i] < 100 {
1121                             self.state.intensity = VirtualConsoleIntensity::Bold;
1122                         }
1123                         self.par[i] -= 60;
1124                     }
1125 
1126                     if self.par[i] >= 30 && self.par[i] <= 37 {
1127                         self.state.color =
1128                             COLOR_TABLE[self.par[i] as usize - 30] | self.state.color & 0xf0;
1129                     } else if self.par[i] >= 40 && self.par[i] <= 47 {
1130                         self.state.color =
1131                             (COLOR_TABLE[self.par[i] as usize - 40] << 4) | self.state.color & 0xf0;
1132                     }
1133                 }
1134             }
1135 
1136             i += 1;
1137         }
1138 
1139         self.update_attr();
1140     }
1141 
1142     /// ##  处理Control Sequence Introducer(控制序列引导符) J字符
1143     /// 该命令用于擦除终端显示区域的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作:
1144     /// - vpar 为 0 时,擦除从光标位置到显示区域末尾的内容;
1145     /// - vpar 为 1 时,擦除从显示区域起始位置到光标位置的内容;
1146     /// - vpar 为 2 或 3 时,分别表示擦除整个显示区域的内容,其中参数 3 还会清除回滚缓冲区的内容。
1147     #[allow(non_snake_case)]
csi_J(&mut self, vpar: u32)1148     fn csi_J(&mut self, vpar: u32) {
1149         let count;
1150         let start;
1151 
1152         match vpar {
1153             0 => {
1154                 // 擦除从光标位置到显示区域末尾的内容
1155                 count = self.screen_buf.len() - self.pos;
1156                 start = self.pos;
1157             }
1158             1 => {
1159                 // 擦除从显示区域起始位置到光标位置的内容
1160                 count = self.pos;
1161                 start = 0;
1162             }
1163             2 => {
1164                 // 擦除整个显示区域的内容
1165                 count = self.screen_buf.len();
1166                 start = 0;
1167             }
1168             3 => {
1169                 // 表示擦除整个显示区域的内容,还会清除回滚缓冲区的内容
1170                 // TODO:当前未实现回滚缓冲
1171                 count = self.screen_buf.len();
1172                 start = 0;
1173             }
1174             _ => {
1175                 return;
1176             }
1177         }
1178 
1179         for i in self.screen_buf[start..(start + count)].iter_mut() {
1180             *i = self.erase_char;
1181         }
1182 
1183         if self.should_update() {
1184             self.do_update_region(start, count)
1185         }
1186 
1187         self.need_wrap = false;
1188     }
1189 
1190     /// ##  处理Control Sequence Introducer(控制序列引导符) K字符
1191     /// 该命令用于擦除终端当前行的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作:
1192     /// - vpar 为 0 时,擦除从光标位置到该行末尾的内容
1193     /// - vpar 为 1 时,擦除从该行起始位置到光标位置的内容
1194     /// - vpar 为 2 时,擦除整个行。
1195     #[allow(non_snake_case)]
csi_K(&mut self, vpar: u32)1196     fn csi_K(&mut self, vpar: u32) {
1197         let count;
1198         let start;
1199 
1200         match vpar {
1201             0 => {
1202                 // 擦除从光标位置到该行末尾的内容
1203                 count = self.cols - self.state.x;
1204                 start = self.pos;
1205             }
1206             1 => {
1207                 // 擦除从该行起始位置到光标位置的内容
1208                 count = self.state.x + 1;
1209                 start = self.pos - self.state.x;
1210             }
1211             2 => {
1212                 // 擦除整个行
1213                 count = self.cols;
1214                 start = self.pos - self.state.x;
1215             }
1216             _ => {
1217                 return;
1218             }
1219         }
1220 
1221         let max_idx = self.screen_buf.len();
1222         for i in self.screen_buf[start..max_idx.min(start + count)].iter_mut() {
1223             *i = self.erase_char;
1224         }
1225 
1226         if self.should_update() {
1227             self.do_update_region(start, count.min(max_idx - start))
1228         }
1229 
1230         self.need_wrap = false;
1231     }
1232 
t416_color(&mut self, mut idx: usize) -> (usize, Option<Color>)1233     fn t416_color(&mut self, mut idx: usize) -> (usize, Option<Color>) {
1234         idx += 1;
1235         if idx > self.npar as usize {
1236             return (idx, None);
1237         }
1238 
1239         if self.par[idx] == 5 && idx < self.npar as usize {
1240             // 256色
1241             idx += 1;
1242             return (idx, Some(Color::from_256(self.par[idx])));
1243         } else if self.par[idx] == 2 && idx + 3 <= self.npar as usize {
1244             // 24位
1245             let color = Color {
1246                 red: self.par[idx + 1] as u16,
1247                 green: self.par[idx + 2] as u16,
1248                 blue: self.par[idx + 3] as u16,
1249                 ..Default::default()
1250             };
1251             idx += 3;
1252             return (idx, Some(color));
1253         } else {
1254             return (idx, None);
1255         }
1256     }
1257 
1258     /// ## 处理终端控制字符
1259     #[inline(never)]
do_control(&mut self, ch: u32)1260     pub fn do_control(&mut self, ch: u32) {
1261         // 首先检查是否处于 ANSI 控制字符串状态
1262         if self.vc_state.is_ansi_control_string() && (8..=13).contains(&ch) {
1263             return;
1264         }
1265 
1266         match ch {
1267             0 => {
1268                 return;
1269             }
1270             7 => {
1271                 // BEL
1272                 if self.vc_state.is_ansi_control_string() {
1273                     self.vc_state = VirtualConsoleState::ESnormal;
1274                 }
1275                 // TODO: 发出声音?
1276                 return;
1277             }
1278             8 => {
1279                 // BS backspace
1280                 self.backspace();
1281                 return;
1282             }
1283             9 => {
1284                 // 水平制表符(Horizontal Tab)
1285                 self.pos -= self.state.x;
1286 
1287                 self.state.x = self
1288                     .tab_stop
1289                     .next_index(self.state.x + 1)
1290                     .unwrap_or(self.cols - 1);
1291                 self.state.x = core::cmp::min(self.state.x, self.cols - 1);
1292 
1293                 self.pos += self.state.x;
1294                 // TODO: notify
1295                 return;
1296             }
1297             10..=12 => {
1298                 // LD line feed
1299                 self.line_feed();
1300                 // TODO: 检查键盘模式
1301                 self.carriage_return();
1302                 return;
1303             }
1304             13 => {
1305                 // CR 回车符
1306                 self.carriage_return();
1307                 return;
1308             }
1309             14 => {
1310                 todo!("Gx_charset todo!");
1311             }
1312             15 => {
1313                 todo!("Gx_charset todo!");
1314             }
1315             24 | 26 => {
1316                 self.vc_state = VirtualConsoleState::ESnormal;
1317                 return;
1318             }
1319             27 => {
1320                 // esc
1321                 self.vc_state = VirtualConsoleState::ESesc;
1322                 return;
1323             }
1324             127 => {
1325                 // delete
1326                 self.delete();
1327                 return;
1328             }
1329             155 => {
1330                 // '['
1331                 self.vc_state = VirtualConsoleState::ESsquare;
1332                 return;
1333             }
1334             _ => {}
1335         }
1336 
1337         match self.vc_state {
1338             VirtualConsoleState::ESesc => {
1339                 self.vc_state = VirtualConsoleState::ESnormal;
1340                 match ch as u8 as char {
1341                     '[' => {
1342                         self.vc_state = VirtualConsoleState::ESsquare;
1343                     }
1344                     ']' => {
1345                         self.vc_state = VirtualConsoleState::ESnonstd;
1346                     }
1347                     '_' => {
1348                         self.vc_state = VirtualConsoleState::ESapc;
1349                     }
1350                     '^' => {
1351                         self.vc_state = VirtualConsoleState::ESpm;
1352                     }
1353                     '%' => {
1354                         self.vc_state = VirtualConsoleState::ESpercent;
1355                     }
1356                     'E' => {
1357                         self.carriage_return();
1358                         self.line_feed();
1359                     }
1360                     'M' => {
1361                         self.reverse_index();
1362                     }
1363                     'D' => {
1364                         self.line_feed();
1365                     }
1366                     'H' => {
1367                         if self.state.x < 256 {
1368                             self.tab_stop.set(self.state.x, true);
1369                         }
1370                     }
1371                     'P' => {
1372                         self.vc_state = VirtualConsoleState::ESdcs;
1373                     }
1374                     'Z' => {
1375                         todo!("Respond ID todo!");
1376                     }
1377                     '7' => self.saved_state = self.state.clone(),
1378                     '8' => self.restore_cursor(),
1379                     '(' => {
1380                         self.vc_state = VirtualConsoleState::ESsetG0;
1381                     }
1382                     ')' => {
1383                         self.vc_state = VirtualConsoleState::ESsetG1;
1384                     }
1385                     '#' => {
1386                         self.vc_state = VirtualConsoleState::EShash;
1387                     }
1388                     'c' => {
1389                         self.reset(true);
1390                     }
1391                     '>' => {
1392                         todo!("clr_kbd todo");
1393                     }
1394                     '=' => {
1395                         todo!("set_kbd todo");
1396                     }
1397                     _ => {}
1398                 }
1399             }
1400             VirtualConsoleState::ESsquare => {
1401                 for i in self.par.iter_mut() {
1402                     *i = 0;
1403                 }
1404                 self.vc_state = VirtualConsoleState::ESgetpars;
1405                 self.npar = 0;
1406                 let c = ch as u8 as char;
1407                 if c == '[' {
1408                     self.vc_state = VirtualConsoleState::ESfunckey;
1409                     return;
1410                 }
1411 
1412                 match c {
1413                     '?' => {
1414                         self.private = Vt102_OP::Pdec;
1415                         return;
1416                     }
1417                     '>' => {
1418                         self.private = Vt102_OP::Pgt;
1419                         return;
1420                     }
1421                     '=' => {
1422                         self.private = Vt102_OP::Peq;
1423                         return;
1424                     }
1425                     '<' => {
1426                         self.private = Vt102_OP::Plt;
1427                         return;
1428                     }
1429                     _ => {}
1430                 }
1431 
1432                 self.private = Vt102_OP::Pecma;
1433                 self.do_getpars(c);
1434             }
1435             VirtualConsoleState::ESgetpars => {
1436                 let c = ch as u8 as char;
1437                 self.do_getpars(c);
1438             }
1439             VirtualConsoleState::ESfunckey => {
1440                 self.vc_state = VirtualConsoleState::ESnormal;
1441                 return;
1442             }
1443             VirtualConsoleState::EShash => {
1444                 self.vc_state = VirtualConsoleState::ESnormal;
1445                 if ch as u8 as char == '8' {
1446                     self.erase_char = (self.erase_char & 0xff00) | 'E' as u16;
1447                     self.csi_J(2);
1448                     self.erase_char = (self.erase_char & 0xff00) | ' ' as u16;
1449                     self.do_update_region(0, self.screen_buf.len());
1450                 }
1451                 return;
1452             }
1453             VirtualConsoleState::ESsetG0 => {
1454                 todo!("SetGx todo");
1455             }
1456             VirtualConsoleState::ESsetG1 => {
1457                 todo!("SetGx todo");
1458             }
1459             VirtualConsoleState::ESpercent => {
1460                 self.vc_state = VirtualConsoleState::ESnormal;
1461                 let c = ch as u8 as char;
1462                 match c {
1463                     '@' => {
1464                         self.utf = false;
1465                         return;
1466                     }
1467                     'G' | '8' => {
1468                         self.utf = true;
1469                         return;
1470                     }
1471                     _ => {}
1472                 }
1473                 return;
1474             }
1475             VirtualConsoleState::EScsiignore => {
1476                 if (20..=0x3f).contains(&ch) {
1477                     return;
1478                 }
1479                 self.vc_state = VirtualConsoleState::ESnormal;
1480                 return;
1481             }
1482             VirtualConsoleState::ESnonstd => {
1483                 let c = ch as u8 as char;
1484                 if c == 'P' {
1485                     for i in self.par.iter_mut() {
1486                         *i = 0;
1487                     }
1488                     self.npar = 0;
1489                     self.vc_state = VirtualConsoleState::ESpalette;
1490                     return;
1491                 } else if c == 'R' {
1492                     self.reset_palette();
1493                     self.vc_state = VirtualConsoleState::ESnormal;
1494                 } else if c.is_ascii_digit() {
1495                     self.vc_state = VirtualConsoleState::ESosc;
1496                 } else {
1497                     self.vc_state = VirtualConsoleState::ESnormal;
1498                 }
1499             }
1500             VirtualConsoleState::ESpalette => {
1501                 let c = ch as u8 as char;
1502                 if c.is_ascii_hexdigit() {
1503                     self.npar += 1;
1504                     self.par[self.npar as usize] = c.to_digit(16).unwrap();
1505 
1506                     if self.npar == 7 {
1507                         let mut i = self.par[0] as usize;
1508                         let mut j = 0;
1509                         self.palette[i].red = self.par[j] as u16;
1510                         j += 1;
1511                         self.palette[i].green = self.par[j] as u16;
1512                         j += 1;
1513                         self.palette[i].blue = self.par[j] as u16;
1514                         j += 1;
1515                         i += 1;
1516                         self.palette[i].red = self.par[j] as u16;
1517                         j += 1;
1518                         self.palette[i].green = self.par[j] as u16;
1519                         j += 1;
1520                         self.palette[i].blue = self.par[j] as u16;
1521                         self.set_palette();
1522                         self.vc_state = VirtualConsoleState::ESnormal;
1523                     }
1524                 }
1525             }
1526             VirtualConsoleState::ESosc => {}
1527             VirtualConsoleState::ESapc => {}
1528             VirtualConsoleState::ESpm => {}
1529             VirtualConsoleState::ESdcs => {}
1530             VirtualConsoleState::ESnormal => {}
1531         }
1532     }
1533 
1534     #[inline(never)]
console_write_normal(&mut self, mut tc: u32, c: u32, draw: &mut DrawRegion) -> bool1535     pub fn console_write_normal(&mut self, mut tc: u32, c: u32, draw: &mut DrawRegion) -> bool {
1536         let mut attr = self.attr;
1537         let himask = self.hi_font_mask;
1538         let charmask = if himask == 0 { 0xff } else { 0x1ff };
1539         let mut width = 1;
1540         // 表示需不需要反转
1541         let mut invert = false;
1542         if self.utf && !self.display_ctrl && FontDesc::is_double_width(c) {
1543             width = 2;
1544         }
1545 
1546         let tmp = self.unicode_to_index(tc);
1547         if tmp & (!charmask as i32) != 0 {
1548             if tmp == -1 || tmp == -2 {
1549                 return false;
1550             }
1551 
1552             // 未找到
1553             if (!self.utf || self.display_ctrl || c < 128) && (c & !charmask) == 0 {
1554                 tc = c;
1555             } else {
1556                 let tmp = self.unicode_to_index(0xfffd);
1557                 if tmp < 0 {
1558                     invert = true;
1559                     let tmp = self.unicode_to_index('?' as u32);
1560                     if tmp < 0 {
1561                         tc = '?' as u32;
1562                     } else {
1563                         tc = tmp as u32;
1564                     }
1565 
1566                     attr = self.invert_attr();
1567                     self.flush(draw);
1568                 }
1569             }
1570         }
1571 
1572         loop {
1573             if self.need_wrap || self.insert_mode {
1574                 self.flush(draw);
1575             }
1576             if self.need_wrap {
1577                 self.carriage_return();
1578                 self.line_feed();
1579             }
1580 
1581             if self.insert_mode {
1582                 self.insert_char(1);
1583             }
1584 
1585             // TODO: 处理unicode screen buf
1586 
1587             if himask != 0 {
1588                 tc = (if (tc & 0x100) != 0 { himask as u32 } else { 0 }) | (tc & 0xff);
1589             }
1590 
1591             tc |= ((attr as u32) << 8) & (!himask as u32);
1592 
1593             // warn!(
1594             //     "ch {} pos {} x {} y {} cols {}",
1595             //     c as u8 as char,
1596             //     self.pos,
1597             //     self.state.x,
1598             //     self.state.y,
1599             //     self.cols,
1600             // );
1601             self.screen_buf[self.pos] = tc as u16;
1602 
1603             if self.should_update() && draw.x.is_none() {
1604                 // 设置draw参数
1605                 draw.x = Some(self.state.x as u32);
1606                 draw.offset = self.pos;
1607             }
1608 
1609             if self.state.x == self.cols - 1 {
1610                 // 需要换行?
1611                 self.need_wrap = self.autowrap;
1612                 draw.size += 1;
1613             } else {
1614                 self.state.x += 1;
1615                 self.pos += 1;
1616                 draw.size += 1;
1617             }
1618 
1619             width -= 1;
1620             if width <= 0 {
1621                 break;
1622             }
1623             let tmp = self.unicode_to_index(' ' as u32);
1624             tc = if tmp < 0 { ' ' as u32 } else { tmp as u32 };
1625         }
1626 
1627         if invert {
1628             self.flush(draw);
1629         }
1630         true
1631     }
1632 
1633     /// ## 当前vc插入nr个字符
insert_char(&mut self, nr: usize)1634     fn insert_char(&mut self, nr: usize) {
1635         // TODO: 管理unicode屏幕信息
1636 
1637         let pos = self.pos;
1638         // 把当前位置以后得字符向后移动nr*2位
1639         self.screen_buf[pos..].rotate_right(nr * 2);
1640 
1641         // 把空出来的位置用erase_char填充
1642         for c in &mut self.screen_buf[pos..(pos + nr * 2)] {
1643             *c = self.erase_char
1644         }
1645 
1646         self.need_wrap = false;
1647 
1648         // 更新本行后面部分
1649         self.do_update_region(self.pos, self.cols - self.state.x);
1650     }
1651 
1652     /// ## 更新虚拟控制台指定区域的显示
do_update_region(&self, mut start: usize, mut count: usize)1653     fn do_update_region(&self, mut start: usize, mut count: usize) {
1654         let ret = self.driver_funcs().con_getxy(self, start);
1655         let (mut x, mut y) = if let Ok((_, tmp_x, tmp_y)) = ret {
1656             // start = tmp_start;
1657             (tmp_x, tmp_y)
1658         } else {
1659             (start % self.cols, start / self.cols)
1660         };
1661 
1662         loop {
1663             // 记录当前字符的属性
1664             let mut attr = self.screen_buf[start] & 0xff00;
1665             let mut startx = x;
1666             let mut size = 0;
1667 
1668             while count != 0 && x < self.cols {
1669                 // 检查属性是否变化,如果属性变了,则将前一个字符先输出
1670                 if attr != (self.screen_buf[start] & 0xff00) && size > 0 {
1671                     let _ = self.driver_funcs().con_putcs(
1672                         self,
1673                         &self.screen_buf[start..],
1674                         size,
1675                         y as u32,
1676                         startx as u32,
1677                     );
1678                     startx = x;
1679                     start += size;
1680                     size = 0;
1681                     attr = self.screen_buf[start] & 0xff00;
1682                 }
1683                 size += 1;
1684                 x += 1;
1685                 count -= 1;
1686             }
1687 
1688             if size > 0 {
1689                 let _ = self.driver_funcs().con_putcs(
1690                     self,
1691                     &self.screen_buf[start..],
1692                     size,
1693                     y as u32,
1694                     startx as u32,
1695                 );
1696             }
1697             if count == 0 {
1698                 break;
1699             }
1700 
1701             // 一行
1702             x = 0;
1703             y += 1;
1704 
1705             let ret = self.driver_funcs().con_getxy(self, start);
1706             if let Ok(ret) = ret {
1707                 start = ret.0;
1708             } else {
1709                 return;
1710             }
1711         }
1712     }
1713 
1714     const UNI_DIRECT_MAKS: u32 = 0x01ff;
1715     const UNI_DIRECT_BASE: u32 = 0xf000;
1716     /// ## unicode字符转对应的坐标,暂时这样写,还没有适配unicode
1717     /// 这里是糊代码的,后面重写
unicode_to_index(&self, ch: u32) -> i321718     fn unicode_to_index(&self, ch: u32) -> i32 {
1719         if ch > 0xfff {
1720             // 未找到
1721             return -4;
1722         } else if ch < 0x20 {
1723             // 不可打印
1724             return -1;
1725         } else if ch == 0xfeff || (0x200b..=0x200f).contains(&ch) {
1726             // 零长空格
1727             return -2;
1728         } else if (ch & !Self::UNI_DIRECT_MAKS) == Self::UNI_DIRECT_BASE {
1729             return (ch & Self::UNI_DIRECT_MAKS) as i32;
1730         }
1731 
1732         // TODO: 暂时这样写,表示不支持
1733         return -3;
1734     }
1735 
invert_attr(&self) -> u81736     fn invert_attr(&self) -> u8 {
1737         if !self.color_mode {
1738             return self.attr ^ 0x08;
1739         }
1740 
1741         if self.hi_font_mask == 0x100 {
1742             return (self.attr & 0x11) | ((self.attr & 0xe0) >> 4) | ((self.attr & 0x0e) << 4);
1743         }
1744 
1745         return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4);
1746     }
1747 
flush(&self, draw: &mut DrawRegion)1748     pub fn flush(&self, draw: &mut DrawRegion) {
1749         if draw.x.is_none() {
1750             return;
1751         }
1752 
1753         let _ = self.driver_funcs().con_putcs(
1754             self,
1755             &self.screen_buf[draw.offset..draw.offset + draw.size],
1756             draw.size,
1757             self.state.y as u32,
1758             draw.x.unwrap(),
1759         );
1760 
1761         draw.x = None;
1762         draw.size = 0;
1763     }
1764 
1765     #[allow(clippy::manual_rotate)]
build_attr( &self, color: u8, intensity: VirtualConsoleIntensity, blink: bool, underline: bool, reverse: bool, italic: bool, ) -> u81766     fn build_attr(
1767         &self,
1768         color: u8,
1769         intensity: VirtualConsoleIntensity,
1770         blink: bool,
1771         underline: bool,
1772         reverse: bool,
1773         italic: bool,
1774     ) -> u8 {
1775         let ret = self
1776             .driver_funcs()
1777             .con_build_attr(self, color, intensity, blink, underline, reverse, italic);
1778 
1779         if let Ok(ret) = ret {
1780             return ret;
1781         }
1782 
1783         let mut ret = color;
1784 
1785         if !self.color_mode {
1786             return intensity as u8
1787                 | (italic as u8) << 1
1788                 | (underline as u8) << 2
1789                 | (reverse as u8) << 3
1790                 | (blink as u8) << 7;
1791         }
1792 
1793         if italic {
1794             ret = (ret & 0xf0) | self.italic_color as u8;
1795         } else if underline {
1796             ret = (ret & 0xf0) | self.underline_color as u8;
1797         } else if intensity == VirtualConsoleIntensity::HalfBright {
1798             ret = (ret & 0xf0) | self.half_color as u8;
1799         }
1800 
1801         if reverse {
1802             ret = (ret & 0x88) | (((ret >> 4) | (ret << 4)) & 0x77);
1803         }
1804 
1805         if blink {
1806             ret ^= 0x80;
1807         }
1808 
1809         if intensity == VirtualConsoleIntensity::Bold {
1810             ret ^= 0x08;
1811         }
1812 
1813         if self.hi_font_mask == 0x100 {
1814             ret <<= 1;
1815         }
1816 
1817         ret
1818     }
1819 
update_attr(&mut self)1820     pub(super) fn update_attr(&mut self) {
1821         self.attr = self.build_attr(
1822             self.state.color,
1823             self.state.intensity,
1824             self.state.blink,
1825             self.state.underline,
1826             self.state.reverse ^ self.screen_mode,
1827             self.state.italic,
1828         );
1829 
1830         self.erase_char = ' ' as u16
1831             | ((self.build_attr(
1832                 self.state.color,
1833                 VirtualConsoleIntensity::Normal,
1834                 self.state.blink,
1835                 false,
1836                 self.screen_mode,
1837                 false,
1838             ) as u16)
1839                 << 8);
1840     }
1841 
default_attr(&mut self)1842     fn default_attr(&mut self) {
1843         self.state.intensity = VirtualConsoleIntensity::Normal;
1844         self.state.italic = false;
1845         self.state.underline = false;
1846         self.state.reverse = false;
1847         self.state.blink = false;
1848         self.state.color = self.def_color;
1849     }
1850 }
1851 
1852 /// ## 虚拟控制台的状态信息
1853 #[derive(Debug, Default, Clone)]
1854 pub struct VirtualConsoleInfo {
1855     // x,y表示光标坐标
1856     pub x: usize,
1857     pub y: usize,
1858     pub color: u8,
1859 
1860     /// 表示字符的强度
1861     intensity: VirtualConsoleIntensity,
1862     /// 斜体
1863     italic: bool,
1864     /// 下划线
1865     underline: bool,
1866     /// 字符闪烁
1867     blink: bool,
1868     /// 前景与背景色反转
1869     reverse: bool,
1870 }
1871 
1872 impl VirtualConsoleInfo {
new(x: usize, y: usize) -> Self1873     pub fn new(x: usize, y: usize) -> Self {
1874         Self {
1875             x,
1876             y,
1877             color: Default::default(),
1878             intensity: Default::default(),
1879             italic: Default::default(),
1880             underline: Default::default(),
1881             blink: Default::default(),
1882             reverse: Default::default(),
1883         }
1884     }
1885 }
1886 
1887 /// 字符强度
1888 #[derive(Debug, Clone, PartialEq, Copy)]
1889 pub enum VirtualConsoleIntensity {
1890     /// 暗淡
1891     HalfBright = 0,
1892     /// 正常
1893     Normal = 1,
1894     /// 粗体
1895     Bold = 2,
1896 }
1897 
1898 impl Default for VirtualConsoleIntensity {
default() -> Self1899     fn default() -> Self {
1900         Self::Normal
1901     }
1902 }
1903 
1904 /// ## 虚拟控制台的状态
1905 ///
1906 /// 可以把VC的接收字符理解为一个状态机
1907 #[derive(Debug, PartialEq, Clone)]
1908 pub enum VirtualConsoleState {
1909     /// 正常状态
1910     ESnormal,
1911     /// 收到了转义字符 \e,即"Escape"字符
1912     ESesc,
1913     /// 收到了 "[" 字符,通常是 ANSI 控制序列的开始
1914     ESsquare,
1915     /// 解析参数状态
1916     ESgetpars,
1917     /// 功能键状态
1918     ESfunckey,
1919     /// 收到了 "#" 字符
1920     EShash,
1921     /// 设置 G0 字符集状态
1922     ESsetG0,
1923     /// 设置 G1 字符集状态
1924     ESsetG1,
1925     /// 收到了 "%" 字符
1926     ESpercent,
1927     /// 忽略 ANSI 控制序列状态
1928     EScsiignore,
1929     /// 非标准字符状态
1930     ESnonstd,
1931     /// 调色板状态
1932     ESpalette,
1933     /// Operating System Command (OSC) 状态
1934     ESosc,
1935     ///  Application Program Command (APC) 状态
1936     ESapc,
1937     /// Privacy Message (PM) 状态
1938     ESpm,
1939     /// Device Control String (DCS) 状态
1940     ESdcs,
1941 }
1942 
1943 impl VirtualConsoleState {
is_ansi_control_string(&self) -> bool1944     pub fn is_ansi_control_string(&self) -> bool {
1945         if *self == Self::ESosc
1946             || *self == Self::ESapc
1947             || *self == Self::ESpm
1948             || *self == Self::ESdcs
1949         {
1950             return true;
1951         }
1952 
1953         false
1954     }
1955 }
1956 
1957 #[derive(Debug, Clone, PartialEq, PartialOrd)]
1958 #[allow(non_camel_case_types)]
1959 pub enum Vt102_OP {
1960     Pecma,
1961     Pdec,
1962     Peq,
1963     Pgt,
1964     Plt,
1965 }
1966 
1967 bitflags! {
1968     #[derive(Default)]
1969     pub struct VcCursor: u32 {
1970         /// 默认
1971         const CUR_DEF			=       0;
1972         /// 无光标
1973         const CUR_NONE			=       1;
1974         /// 下划线形式
1975         const CUR_UNDERLINE		=	    2;
1976         /// 光标占据底部的三分之一
1977         const CUR_LOWER_THIRD	=	    3;
1978         /// 光标占据底部的一半
1979         const CUR_LOWER_HALF	=       4;
1980         ///  光标占据底部的三分之二
1981         const CUR_TWO_THIRDS	=       5;
1982         /// 光标为块状(方块)形式
1983         const CUR_BLOCK			=       6;
1984         /// 光标属性,用于指示软件光标
1985         const CUR_SW			=	0x000010;
1986         /// 光标属性,用于指示光标是否始终在背景上显示
1987         const CUR_ALWAYS_BG		=	0x000020;
1988         /// 光标属性,用于指示前景和背景是否反转
1989         const CUR_INVERT_FG_BG	=	0x000040;
1990         /// 光标前景色属性,用于指定光标的前景色
1991         const CUR_FG			=	0x000700;
1992         /// 光标背景色属性,用于指定光标的背景色
1993         const CUR_BG			=	0x007000;
1994     }
1995 }
1996 
1997 impl VcCursor {
make_cursor(size: u32, change: u32, set: u32) -> Self1998     pub fn make_cursor(size: u32, change: u32, set: u32) -> Self {
1999         unsafe { Self::from_bits_unchecked(size | (change << 8) | (set << 16)) }
2000     }
2001 
cursor_size(&self) -> Self2002     pub fn cursor_size(&self) -> Self {
2003         Self::from_bits_truncate(self.bits & 0x00000f)
2004     }
2005 
cursor_set(&self) -> u322006     pub fn cursor_set(&self) -> u32 {
2007         (self.bits & 0xff0000) >> 8
2008     }
2009 
cursor_change(&self) -> u322010     pub fn cursor_change(&self) -> u32 {
2011         self.bits & 0x00ff00
2012     }
2013 }
2014 
2015 #[derive(Debug, PartialEq)]
2016 #[allow(dead_code)]
2017 pub enum CursorOperation {
2018     Draw,
2019     Erase,
2020     Move,
2021 }
2022 
2023 #[derive(Debug, PartialEq, Clone, Copy)]
2024 pub enum ScrollDir {
2025     Up,
2026     Down,
2027 }
2028