xref: /DragonOS/kernel/src/driver/tty/virtual_terminal/virtual_console.rs (revision dfe53cf087ef4c7b6db63d992906b062dc63e93f)
152da9a59SGnoCiYeH use core::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
252da9a59SGnoCiYeH 
352da9a59SGnoCiYeH use alloc::{
452da9a59SGnoCiYeH     sync::{Arc, Weak},
552da9a59SGnoCiYeH     vec::Vec,
652da9a59SGnoCiYeH };
752da9a59SGnoCiYeH use bitmap::{traits::BitMapOps, StaticBitmap};
852da9a59SGnoCiYeH 
952da9a59SGnoCiYeH use crate::{
1052bcb59eSGnoCiYeH     driver::{
1152bcb59eSGnoCiYeH         serial::serial8250::send_to_default_serial8250_port,
12*dfe53cf0SGnoCiYeH         tty::{
13*dfe53cf0SGnoCiYeH             console::ConsoleSwitch,
14*dfe53cf0SGnoCiYeH             tty_port::{DefaultTtyPort, TtyPort},
15*dfe53cf0SGnoCiYeH             ConsoleFont, KDMode,
16*dfe53cf0SGnoCiYeH         },
1752bcb59eSGnoCiYeH     },
1852da9a59SGnoCiYeH     libs::{font::FontDesc, rwlock::RwLock},
1952da9a59SGnoCiYeH     process::Pid,
2052da9a59SGnoCiYeH };
2152da9a59SGnoCiYeH 
2252da9a59SGnoCiYeH use super::{
2352da9a59SGnoCiYeH     console_map::{TranslationMap, TranslationMapType},
2452da9a59SGnoCiYeH     Color, DrawRegion, VtMode, VtModeData, COLOR_TABLE, DEFAULT_BLUE, DEFAULT_GREEN, DEFAULT_RED,
2552da9a59SGnoCiYeH };
2652da9a59SGnoCiYeH 
2752da9a59SGnoCiYeH pub(super) const NPAR: usize = 16;
2852da9a59SGnoCiYeH 
2952da9a59SGnoCiYeH lazy_static! {
3052da9a59SGnoCiYeH     /// 是否已经添加了软光标
3152da9a59SGnoCiYeH     pub(super) static ref SOFTCURSOR_ORIGINAL: RwLock<Option<VcCursor>> = RwLock::new(None);
3252da9a59SGnoCiYeH 
3352da9a59SGnoCiYeH 
3452da9a59SGnoCiYeH }
3552da9a59SGnoCiYeH 
36da152319SLoGin pub static CURRENT_VCNUM: AtomicIsize = AtomicIsize::new(-1);
37da152319SLoGin 
38da152319SLoGin pub static CONSOLE_BLANKED: AtomicBool = AtomicBool::new(false);
39da152319SLoGin 
4052da9a59SGnoCiYeH /// ## 虚拟控制台的信息
4152da9a59SGnoCiYeH #[derive(Debug, Clone)]
4252da9a59SGnoCiYeH pub struct VirtualConsoleData {
4352da9a59SGnoCiYeH     pub num: usize,
4452da9a59SGnoCiYeH     pub state: VirtualConsoleInfo,
4552da9a59SGnoCiYeH     pub saved_state: VirtualConsoleInfo,
4652da9a59SGnoCiYeH     /// 最大列数
4752da9a59SGnoCiYeH     pub cols: usize,
4852da9a59SGnoCiYeH     /// 最大行数
4952da9a59SGnoCiYeH     pub rows: usize,
5052da9a59SGnoCiYeH     // ///  每行的字节数
5152da9a59SGnoCiYeH     // pub bytes_per_row: usize,
5252da9a59SGnoCiYeH     /// 扫描行数
5352da9a59SGnoCiYeH     pub scan_lines: usize,
5452da9a59SGnoCiYeH     /// 字符单元高度
5552da9a59SGnoCiYeH     pub cell_height: u32,
5652da9a59SGnoCiYeH 
5752da9a59SGnoCiYeH     // /// 实际屏幕地址的开始
5852da9a59SGnoCiYeH     // pub screen_base: VirtAddr,
5952da9a59SGnoCiYeH     // /// 实际屏幕的结束
6052da9a59SGnoCiYeH     // pub scr_end: u64,
6152da9a59SGnoCiYeH     /// 可见窗口的开始
6252da9a59SGnoCiYeH     pub visible_origin: usize,
6352da9a59SGnoCiYeH     /// 滚动窗口的顶部
6452da9a59SGnoCiYeH     pub top: usize,
6552da9a59SGnoCiYeH     /// 滚动窗口的底部
6652da9a59SGnoCiYeH     pub bottom: usize,
6752da9a59SGnoCiYeH     /// 当前读取位置
6852da9a59SGnoCiYeH     pub pos: usize,
6952da9a59SGnoCiYeH 
7052da9a59SGnoCiYeH     /// 颜色集合
7152da9a59SGnoCiYeH     pub palette: [Color; 16],
7252da9a59SGnoCiYeH     /// 默认颜色
7352da9a59SGnoCiYeH     pub def_color: u8,
7452da9a59SGnoCiYeH     /// 下划线颜色
7552da9a59SGnoCiYeH     pub underline_color: u32,
7652da9a59SGnoCiYeH     /// 斜体颜色
7752da9a59SGnoCiYeH     pub italic_color: u32,
7852da9a59SGnoCiYeH     /// 半强度颜色
7952da9a59SGnoCiYeH     pub half_color: u32,
8052da9a59SGnoCiYeH 
8152da9a59SGnoCiYeH     pub mode: KDMode,
8252da9a59SGnoCiYeH     pub vt_mode: VtModeData,
8352da9a59SGnoCiYeH 
8452da9a59SGnoCiYeH     /// 是否启用颜色
8552da9a59SGnoCiYeH     pub color_mode: bool,
8652da9a59SGnoCiYeH 
8752da9a59SGnoCiYeH     // 字符
8852da9a59SGnoCiYeH     pub hi_font_mask: u16,
8952da9a59SGnoCiYeH     pub font: ConsoleFont,
9052da9a59SGnoCiYeH 
9152da9a59SGnoCiYeH     pub erase_char: u16,
9252da9a59SGnoCiYeH 
9352da9a59SGnoCiYeH     pub complement_mask: u16,
9452da9a59SGnoCiYeH     pub s_complement_mask: u16,
9552da9a59SGnoCiYeH 
9652da9a59SGnoCiYeH     pub cursor_blink_ms: u16,
9752da9a59SGnoCiYeH 
9852da9a59SGnoCiYeH     pub pid: Option<Pid>,
9952da9a59SGnoCiYeH     pub index: usize,
10052da9a59SGnoCiYeH 
10152da9a59SGnoCiYeH     pub vc_state: VirtualConsoleState,
10252da9a59SGnoCiYeH 
10352da9a59SGnoCiYeH     // 一些标志
10452da9a59SGnoCiYeH     /// 指示是否显示 ASCII 字符小于 32 的控制字符(vc_disp_ctrl)
10552da9a59SGnoCiYeH     pub display_ctrl: bool,
10652da9a59SGnoCiYeH     /// 指示是否切换高位(meta)位。Meta 键是一个特殊的按键,用于扩展字符集。
10752da9a59SGnoCiYeH     pub toggle_meta: bool,
10852da9a59SGnoCiYeH     /// 表示屏幕模式(vc_decscnm)
10952da9a59SGnoCiYeH     pub screen_mode: bool,
11052da9a59SGnoCiYeH     /// 指定光标移动的起始位置,是相对于屏幕的左上角还是相对于当前页的左上角(vc_decom)
11152da9a59SGnoCiYeH     pub origin_mode: bool,
11252da9a59SGnoCiYeH     /// 控制光标到达行末时是否自动换行(vc_decawm)
11352da9a59SGnoCiYeH     pub autowrap: bool,
11452da9a59SGnoCiYeH     /// 控制光标的可见性(vc_deccm)
11552da9a59SGnoCiYeH     pub cursor_visible: bool,
11652da9a59SGnoCiYeH     /// 光标相关
11752da9a59SGnoCiYeH     pub cursor_type: VcCursor,
11852da9a59SGnoCiYeH     /// 控制插入或替换模式(vc_decim)
11952da9a59SGnoCiYeH     pub insert_mode: bool,
12052da9a59SGnoCiYeH     /// 表示一些私有模式或状态,通常由特定终端实现定义(vc_priv)
12152da9a59SGnoCiYeH     pub private: Vt102_OP,
12252da9a59SGnoCiYeH     /// 是否需要进行自动换行
12352da9a59SGnoCiYeH     pub need_wrap: bool,
12452da9a59SGnoCiYeH     /// 控制鼠标事件的报告方式
12552da9a59SGnoCiYeH     pub report_mouse: u8,
12652da9a59SGnoCiYeH     /// 指示终端是否使用 UTF-8 编码
12752da9a59SGnoCiYeH     pub utf: bool,
12852da9a59SGnoCiYeH     /// UTF-8 编码的字符计数,表示还需要多少个字节才能够构建完成
12952da9a59SGnoCiYeH     pub utf_count: u8,
13052da9a59SGnoCiYeH     /// UTF-8 编码的字符,表示正在构建的utf字符
13152da9a59SGnoCiYeH     pub utf_char: u32,
13252da9a59SGnoCiYeH     /// 构建utf时需要的参数,表示目前接收了多少个字节的数据来构建utf字符
13352da9a59SGnoCiYeH     pub npar: u32,
13452da9a59SGnoCiYeH     ///
13552da9a59SGnoCiYeH     pub par: [u32; NPAR],
13652da9a59SGnoCiYeH 
13752da9a59SGnoCiYeH     /// 字符转换表 用于将输入字符映射到特定的字符
13852da9a59SGnoCiYeH     pub translate: TranslationMap,
13952da9a59SGnoCiYeH 
14052da9a59SGnoCiYeH     pub tab_stop: StaticBitmap<256>,
14152da9a59SGnoCiYeH 
14252da9a59SGnoCiYeH     pub attr: u8,
14352da9a59SGnoCiYeH 
14452da9a59SGnoCiYeH     /// vc缓冲区
14552da9a59SGnoCiYeH     pub screen_buf: Vec<u16>,
14652da9a59SGnoCiYeH 
14752da9a59SGnoCiYeH     /// 对应的Console Driver funcs
14852da9a59SGnoCiYeH     driver_funcs: Option<Weak<dyn ConsoleSwitch>>,
149*dfe53cf0SGnoCiYeH 
150*dfe53cf0SGnoCiYeH     /// 对应端口
151*dfe53cf0SGnoCiYeH     port: Arc<dyn TtyPort>,
15252da9a59SGnoCiYeH }
15352da9a59SGnoCiYeH 
15452da9a59SGnoCiYeH impl VirtualConsoleData {
15552bcb59eSGnoCiYeH     #[inline(never)]
15652da9a59SGnoCiYeH     pub fn new(num: usize) -> Self {
15752da9a59SGnoCiYeH         Self {
15852da9a59SGnoCiYeH             state: VirtualConsoleInfo::new(0, 0),
15952da9a59SGnoCiYeH             saved_state: Default::default(),
16052da9a59SGnoCiYeH             cols: Default::default(),
16152da9a59SGnoCiYeH             rows: Default::default(),
16252da9a59SGnoCiYeH             // bytes_per_row: Default::default(),
16352da9a59SGnoCiYeH             scan_lines: Default::default(),
16452da9a59SGnoCiYeH             cell_height: Default::default(),
16552da9a59SGnoCiYeH             // origin: Default::default(),
16652da9a59SGnoCiYeH             // scr_end: Default::default(),
16752da9a59SGnoCiYeH             visible_origin: Default::default(),
16852da9a59SGnoCiYeH             top: Default::default(),
16952da9a59SGnoCiYeH             bottom: Default::default(),
17052da9a59SGnoCiYeH             palette: [Default::default(); 16],
17152da9a59SGnoCiYeH             def_color: Default::default(),
17252da9a59SGnoCiYeH             underline_color: Default::default(),
17352da9a59SGnoCiYeH             italic_color: Default::default(),
17452da9a59SGnoCiYeH             half_color: Default::default(),
17552da9a59SGnoCiYeH             mode: Default::default(),
17652da9a59SGnoCiYeH             color_mode: Default::default(),
17752da9a59SGnoCiYeH             hi_font_mask: Default::default(),
17852da9a59SGnoCiYeH             erase_char: Default::default(),
17952da9a59SGnoCiYeH             complement_mask: Default::default(),
18052da9a59SGnoCiYeH             s_complement_mask: Default::default(),
18152da9a59SGnoCiYeH             cursor_blink_ms: 200,
18252da9a59SGnoCiYeH             pos: Default::default(),
18352da9a59SGnoCiYeH             vt_mode: VtModeData {
18452da9a59SGnoCiYeH                 mode: VtMode::Auto,
18552da9a59SGnoCiYeH                 relsig: 0,
18652da9a59SGnoCiYeH                 acqsig: 0,
18752da9a59SGnoCiYeH             },
18852da9a59SGnoCiYeH             pid: None,
18952da9a59SGnoCiYeH             index: 0,
19052da9a59SGnoCiYeH             font: Default::default(),
19152da9a59SGnoCiYeH             vc_state: VirtualConsoleState::ESnormal,
19252da9a59SGnoCiYeH             display_ctrl: Default::default(),
19352da9a59SGnoCiYeH             toggle_meta: Default::default(),
19452da9a59SGnoCiYeH             screen_mode: Default::default(),
19552da9a59SGnoCiYeH             origin_mode: Default::default(),
19652da9a59SGnoCiYeH             autowrap: Default::default(),
19752da9a59SGnoCiYeH             cursor_visible: Default::default(),
19852da9a59SGnoCiYeH             insert_mode: Default::default(),
199b5b571e0SLoGin             private: Vt102_OP::Pecma,
20052da9a59SGnoCiYeH             need_wrap: Default::default(),
20152da9a59SGnoCiYeH             report_mouse: Default::default(),
20252da9a59SGnoCiYeH             utf: Default::default(),
20352da9a59SGnoCiYeH             utf_count: Default::default(),
20452da9a59SGnoCiYeH             utf_char: Default::default(),
205b5b571e0SLoGin             translate: TranslationMap::new(TranslationMapType::Lat1),
20652da9a59SGnoCiYeH             npar: Default::default(),
20752da9a59SGnoCiYeH             tab_stop: StaticBitmap::new(),
20852da9a59SGnoCiYeH             par: [0; 16],
20952da9a59SGnoCiYeH             attr: Default::default(),
21052da9a59SGnoCiYeH             screen_buf: Default::default(),
21152da9a59SGnoCiYeH             driver_funcs: None,
21252da9a59SGnoCiYeH             cursor_type: VcCursor::empty(),
21352da9a59SGnoCiYeH             num,
214*dfe53cf0SGnoCiYeH             port: Arc::new(DefaultTtyPort::new()),
21552da9a59SGnoCiYeH         }
21652da9a59SGnoCiYeH     }
21752da9a59SGnoCiYeH 
218*dfe53cf0SGnoCiYeH     #[inline]
219*dfe53cf0SGnoCiYeH     pub fn port(&self) -> Arc<dyn TtyPort> {
220*dfe53cf0SGnoCiYeH         self.port.clone()
221*dfe53cf0SGnoCiYeH     }
222*dfe53cf0SGnoCiYeH 
22352da9a59SGnoCiYeH     pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) {
224b5b571e0SLoGin         if let Some(rows) = rows {
225b5b571e0SLoGin             self.rows = rows;
22652da9a59SGnoCiYeH         }
227b5b571e0SLoGin         if let Some(cols) = cols {
228b5b571e0SLoGin             self.cols = cols;
22952da9a59SGnoCiYeH         }
23052da9a59SGnoCiYeH 
23152da9a59SGnoCiYeH         self.pos = self.cols * self.state.y + self.state.x;
23252da9a59SGnoCiYeH         // self.bytes_per_row = self.cols << 1;
23352da9a59SGnoCiYeH 
23452da9a59SGnoCiYeH         self.def_color = 15; // white
23552da9a59SGnoCiYeH         self.italic_color = 2; // green
23652da9a59SGnoCiYeH         self.underline_color = 3; // cyan
23752da9a59SGnoCiYeH         self.half_color = 0x08; // grey
23852da9a59SGnoCiYeH 
23952da9a59SGnoCiYeH         self.reset(clear);
24052da9a59SGnoCiYeH 
24152da9a59SGnoCiYeH         self.screen_buf.resize(self.cols * self.rows, 0);
24252da9a59SGnoCiYeH     }
24352da9a59SGnoCiYeH 
24452da9a59SGnoCiYeH     pub fn should_update(&self) -> bool {
24552da9a59SGnoCiYeH         self.is_visible() && !CONSOLE_BLANKED.load(Ordering::SeqCst)
24652da9a59SGnoCiYeH     }
24752da9a59SGnoCiYeH 
24852da9a59SGnoCiYeH     pub fn is_visible(&self) -> bool {
24952da9a59SGnoCiYeH         let cur_vc = CURRENT_VCNUM.load(Ordering::SeqCst);
25052da9a59SGnoCiYeH         if cur_vc == -1 {
25152da9a59SGnoCiYeH             return false;
25252da9a59SGnoCiYeH         }
25352da9a59SGnoCiYeH 
25452da9a59SGnoCiYeH         cur_vc as usize == self.num
25552da9a59SGnoCiYeH     }
25652da9a59SGnoCiYeH 
25752da9a59SGnoCiYeH     fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> {
25852da9a59SGnoCiYeH         self.driver_funcs.as_ref().unwrap().upgrade().unwrap()
25952da9a59SGnoCiYeH     }
26052da9a59SGnoCiYeH 
26152da9a59SGnoCiYeH     pub(super) fn set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>) {
26252da9a59SGnoCiYeH         self.driver_funcs = Some(func);
26352da9a59SGnoCiYeH     }
26452da9a59SGnoCiYeH 
26552da9a59SGnoCiYeH     pub(super) fn reset(&mut self, do_clear: bool) {
26652da9a59SGnoCiYeH         self.mode = KDMode::KdText;
26752da9a59SGnoCiYeH         // unicode?
26852da9a59SGnoCiYeH         self.vt_mode.mode = VtMode::Auto;
26952da9a59SGnoCiYeH         self.vt_mode.acqsig = 0;
27052da9a59SGnoCiYeH         self.vt_mode.relsig = 0;
27152da9a59SGnoCiYeH         self.display_ctrl = false;
27252da9a59SGnoCiYeH         self.toggle_meta = false;
27352da9a59SGnoCiYeH         self.screen_mode = false;
27452da9a59SGnoCiYeH         self.origin_mode = false;
27552da9a59SGnoCiYeH         self.autowrap = true;
27652da9a59SGnoCiYeH         self.cursor_visible = true;
27752da9a59SGnoCiYeH         self.insert_mode = false;
27852da9a59SGnoCiYeH         self.need_wrap = false;
27952da9a59SGnoCiYeH         self.report_mouse = 0;
28052da9a59SGnoCiYeH         self.utf_count = 0;
281b5b571e0SLoGin         self.translate = TranslationMap::new(TranslationMapType::Lat1);
28252da9a59SGnoCiYeH         self.utf = true;
28352da9a59SGnoCiYeH         self.pid = None;
28452da9a59SGnoCiYeH         self.vc_state = VirtualConsoleState::ESnormal;
28552da9a59SGnoCiYeH         self.reset_palette();
28652bcb59eSGnoCiYeH         // self.cursor_type = VcCursor::CUR_UNDERLINE;
28752bcb59eSGnoCiYeH         self.cursor_type = VcCursor::CUR_BLOCK;
28852da9a59SGnoCiYeH 
28952da9a59SGnoCiYeH         self.default_attr();
29052da9a59SGnoCiYeH         self.update_attr();
29152da9a59SGnoCiYeH 
29252da9a59SGnoCiYeH         self.tab_stop.set_all(false);
29352da9a59SGnoCiYeH 
29452da9a59SGnoCiYeH         for i in (0..256).step_by(8) {
29552da9a59SGnoCiYeH             self.tab_stop.set(i, true);
29652da9a59SGnoCiYeH         }
29752da9a59SGnoCiYeH 
29852da9a59SGnoCiYeH         self.state.x = 0;
29952da9a59SGnoCiYeH         self.state.y = 0;
30052da9a59SGnoCiYeH         self.pos = 0;
30152da9a59SGnoCiYeH 
30252da9a59SGnoCiYeH         if do_clear {
30352da9a59SGnoCiYeH             self.csi_J(2);
30452da9a59SGnoCiYeH         }
30552da9a59SGnoCiYeH     }
30652da9a59SGnoCiYeH 
30752da9a59SGnoCiYeH     fn reset_palette(&mut self) {
30852da9a59SGnoCiYeH         for (idx, color) in self.palette.iter_mut().enumerate() {
30952da9a59SGnoCiYeH             color.red = DEFAULT_RED[idx];
31052da9a59SGnoCiYeH             color.green = DEFAULT_GREEN[idx];
31152da9a59SGnoCiYeH             color.blue = DEFAULT_BLUE[idx];
31252da9a59SGnoCiYeH         }
31352da9a59SGnoCiYeH 
31452da9a59SGnoCiYeH         self.set_palette();
31552da9a59SGnoCiYeH     }
31652da9a59SGnoCiYeH 
31752da9a59SGnoCiYeH     fn set_palette(&self) {
31852da9a59SGnoCiYeH         if self.mode != KDMode::KdGraphics {
31952da9a59SGnoCiYeH             // todo: 通知driver层的Console
32052da9a59SGnoCiYeH             let _ = self.driver_funcs().con_set_palette(self, COLOR_TABLE);
32152da9a59SGnoCiYeH         }
32252da9a59SGnoCiYeH     }
32352da9a59SGnoCiYeH 
32452da9a59SGnoCiYeH     /// ## 翻译字符,将字符转换为终端控制符
32552da9a59SGnoCiYeH     /// ### 参数
32652da9a59SGnoCiYeH     ///
32752da9a59SGnoCiYeH     /// ### c: 需要转换的字符
32852da9a59SGnoCiYeH     ///
32952da9a59SGnoCiYeH     /// ### 返回值
33052da9a59SGnoCiYeH     /// ### (转换后的字符:i32,是否需要更多的数据才能进行转换:bool)
33152da9a59SGnoCiYeH     pub(super) fn translate(&mut self, c: &mut u32) -> (Option<u32>, bool) {
33252da9a59SGnoCiYeH         if self.vc_state != VirtualConsoleState::ESnormal {
33352da9a59SGnoCiYeH             // 在控制字符状态下不需要翻译
33452da9a59SGnoCiYeH             return (Some(*c), false);
33552da9a59SGnoCiYeH         }
33652da9a59SGnoCiYeH         if self.utf && !self.display_ctrl {
33752da9a59SGnoCiYeH             // utf模式并且不显示控制字符
33852da9a59SGnoCiYeH             let (ret, rescan) = self.translate_unicode(*c);
339b5b571e0SLoGin             if let Some(ret) = ret {
340b5b571e0SLoGin                 *c = ret;
34152da9a59SGnoCiYeH             }
34252da9a59SGnoCiYeH             return (ret, rescan);
34352da9a59SGnoCiYeH         }
34452da9a59SGnoCiYeH 
34552da9a59SGnoCiYeH         return (Some(self.translate_ascii(*c)), false);
34652da9a59SGnoCiYeH     }
34752da9a59SGnoCiYeH 
34852da9a59SGnoCiYeH     /// 该数组包含每个字节序列长度变化的阈值
34952da9a59SGnoCiYeH     /// 即如果由两个字节组成的unicode字符,则长度应该在UTF8_LENGTH_CHANGES[0] ~ UTF8_LENGTH_CHANGES[1]之间
35052da9a59SGnoCiYeH     const UTF8_LENGTH_CHANGES: &'static [u32] = &[
35152da9a59SGnoCiYeH         0x0000007f, 0x000007ff, 0x0000ffff, 0x001fffff, 0x03ffffff, 0x7fffffff,
35252da9a59SGnoCiYeH     ];
35352da9a59SGnoCiYeH 
35452da9a59SGnoCiYeH     /// ## 翻译字符,将UTF-8 编码的字符转换为 Unicode 编码
35552da9a59SGnoCiYeH     /// ### 参数
35652da9a59SGnoCiYeH     ///
35752da9a59SGnoCiYeH     /// ### c: 需要转换的字符
35852da9a59SGnoCiYeH     ///
35952da9a59SGnoCiYeH     /// ### 返回值
36052da9a59SGnoCiYeH     /// ### (转换后的字符:i32,是否需要重新传入该字符:bool)
36152da9a59SGnoCiYeH     ///
36252da9a59SGnoCiYeH     /// !!! 注意,该函数返回true时,元组的第一个数据是无效数据(未转换完成)
36352da9a59SGnoCiYeH     fn translate_unicode(&mut self, c: u32) -> (Option<u32>, bool) {
36452da9a59SGnoCiYeH         // 收到的字符不是首个
3657c958c9eSVal213         if (c & 0xc0) == 0x80 {
36652da9a59SGnoCiYeH             // 已经不需要继续的字符了,说明这个字符是非法的
36752da9a59SGnoCiYeH             if self.utf_count == 0 {
36852da9a59SGnoCiYeH                 return (Some(0xfffd), false);
36952da9a59SGnoCiYeH             }
37052da9a59SGnoCiYeH 
37152da9a59SGnoCiYeH             self.utf_char = (self.utf_char << 6) | (c & 0x3f);
37252da9a59SGnoCiYeH             self.npar += 1;
37352da9a59SGnoCiYeH 
37452da9a59SGnoCiYeH             self.utf_count -= 1;
37552da9a59SGnoCiYeH             if self.utf_count > 0 {
37652da9a59SGnoCiYeH                 // 表示需要更多字节
37752da9a59SGnoCiYeH                 return (None, false);
37852da9a59SGnoCiYeH             }
37952da9a59SGnoCiYeH 
38052da9a59SGnoCiYeH             let c = self.utf_char;
38152da9a59SGnoCiYeH 
38252da9a59SGnoCiYeH             // 先检查一遍是否合格
38352da9a59SGnoCiYeH             if c <= Self::UTF8_LENGTH_CHANGES[self.npar as usize - 1]
38452da9a59SGnoCiYeH                 || c > Self::UTF8_LENGTH_CHANGES[self.npar as usize]
38552da9a59SGnoCiYeH             {
38652da9a59SGnoCiYeH                 return (Some(0xfffd), false);
38752da9a59SGnoCiYeH             }
38852da9a59SGnoCiYeH 
38952da9a59SGnoCiYeH             return (Some(Self::sanitize_unicode(c)), false);
39052da9a59SGnoCiYeH         }
39152da9a59SGnoCiYeH 
39252da9a59SGnoCiYeH         // 接收到单个ASCII字符或者一个序列的首字符,且上次的未处理完,则上一个字符视为无效,则需要重新传入该字符处理
39352da9a59SGnoCiYeH         if self.utf_count > 0 {
39452da9a59SGnoCiYeH             self.utf_count = 0;
39552da9a59SGnoCiYeH             return (Some(0xfffd), true);
39652da9a59SGnoCiYeH         }
39752da9a59SGnoCiYeH 
39852da9a59SGnoCiYeH         // ascii
39952da9a59SGnoCiYeH         if c <= 0x7f {
40052da9a59SGnoCiYeH             return (Some(c), false);
40152da9a59SGnoCiYeH         }
40252da9a59SGnoCiYeH 
40352da9a59SGnoCiYeH         // 第一个字节
40452da9a59SGnoCiYeH         self.npar = 0;
40552da9a59SGnoCiYeH         if (c & 0xe0) == 0xc0 {
40652da9a59SGnoCiYeH             self.utf_count = 1;
40752da9a59SGnoCiYeH             self.utf_char = c & 0x1f;
40852da9a59SGnoCiYeH         } else if (c & 0xf0) == 0xe0 {
40952da9a59SGnoCiYeH             self.utf_count = 2;
41052da9a59SGnoCiYeH             self.utf_char = c & 0x0f;
41152da9a59SGnoCiYeH         } else if (c & 0xf8) == 0xf0 {
41252da9a59SGnoCiYeH             self.utf_count = 3;
41352da9a59SGnoCiYeH             self.utf_char = c & 0x07;
41452da9a59SGnoCiYeH         } else if (c & 0xfc) == 0xf8 {
41552da9a59SGnoCiYeH             self.utf_count = 4;
41652da9a59SGnoCiYeH             self.utf_char = c & 0x03;
41752da9a59SGnoCiYeH         } else if (c & 0xfe) == 0xfc {
41852da9a59SGnoCiYeH             self.utf_count = 5;
41952da9a59SGnoCiYeH             self.utf_char = c & 0x01;
42052da9a59SGnoCiYeH         } else {
42152da9a59SGnoCiYeH             /* 254 and 255 are invalid */
42252da9a59SGnoCiYeH             return (Some(0xfffd), false);
42352da9a59SGnoCiYeH         }
42452da9a59SGnoCiYeH 
42552da9a59SGnoCiYeH         (None, false)
42652da9a59SGnoCiYeH     }
42752da9a59SGnoCiYeH 
42852da9a59SGnoCiYeH     /// ## 翻译字符,将字符转换为Ascii
42952da9a59SGnoCiYeH     fn translate_ascii(&self, c: u32) -> u32 {
43052da9a59SGnoCiYeH         let mut c = c;
43152da9a59SGnoCiYeH         if self.toggle_meta {
43252da9a59SGnoCiYeH             c |= 0x80;
43352da9a59SGnoCiYeH         }
43452da9a59SGnoCiYeH 
43552da9a59SGnoCiYeH         return self.translate.translate(c) as u32;
43652da9a59SGnoCiYeH     }
43752da9a59SGnoCiYeH 
43852da9a59SGnoCiYeH     /// ## 用于替换无效的 Unicode 代码点(code points)。
43952da9a59SGnoCiYeH     /// Unicode 代码点的范围是从 U+0000 到 U+10FFFF,
44052da9a59SGnoCiYeH     /// 但是有一些特殊的代码点是无效的或者保留给特定用途的。
44152da9a59SGnoCiYeH     /// 这个函数的主要目的是将无效的 Unicode 代码点替换为 U+FFFD,即 Unicode 替代字符。
44252da9a59SGnoCiYeH     fn sanitize_unicode(c: u32) -> u32 {
443b5b571e0SLoGin         if (0xd800..=0xdfff).contains(&c) || c == 0xfffe || c == 0xffff {
44452da9a59SGnoCiYeH             return 0xfffd;
44552da9a59SGnoCiYeH         }
44652da9a59SGnoCiYeH         return c;
44752da9a59SGnoCiYeH     }
44852da9a59SGnoCiYeH 
44952da9a59SGnoCiYeH     /// 用于表示小于 32 的字符中,哪些字符对应的位被设置为 1,
45052da9a59SGnoCiYeH     /// 表示这些字符会触发一些特殊的动作,比如光标移动等。
45152da9a59SGnoCiYeH     /// 这些字符在 disp_ctrl 模式未开启时不应该被显示为图形符号
45252da9a59SGnoCiYeH     const CTRL_ACTION: u32 = 0x0d00ff81;
45352da9a59SGnoCiYeH     /// 用于表示哪些控制字符是始终显示的,即便 disp_ctrl 模式未开启。
45452da9a59SGnoCiYeH     /// 这些字符对于终端来说是必要的,显示它们是为了保证终端正常工作。
45552da9a59SGnoCiYeH     /// 这些字符在 disp_ctrl 模式开启或关闭时都应该显示为控制字符。
45652da9a59SGnoCiYeH     const CTRL_ALWAYS: u32 = 0x0800f501;
45752da9a59SGnoCiYeH 
45852da9a59SGnoCiYeH     /// ## 用于判断tc(终端字符)在当前VC下是不是需要显示的控制字符
45952da9a59SGnoCiYeH     pub(super) fn is_control(&self, tc: u32, c: u32) -> bool {
46052da9a59SGnoCiYeH         // 当前vc状态机不在正常状态,即在接收特殊字符的状态,则是控制字符
46152da9a59SGnoCiYeH         if self.vc_state != VirtualConsoleState::ESnormal {
46252da9a59SGnoCiYeH             return true;
46352da9a59SGnoCiYeH         }
46452da9a59SGnoCiYeH 
46552da9a59SGnoCiYeH         if tc == 0 {
46652da9a59SGnoCiYeH             return true;
46752da9a59SGnoCiYeH         }
46852da9a59SGnoCiYeH 
46952da9a59SGnoCiYeH         if c < 32 {
47052da9a59SGnoCiYeH             if self.display_ctrl {
47152da9a59SGnoCiYeH                 // 查看在位图中是否有该字符
47252da9a59SGnoCiYeH                 return Self::CTRL_ALWAYS & (1 << c) != 0;
47352da9a59SGnoCiYeH             } else {
47452da9a59SGnoCiYeH                 return self.utf || (Self::CTRL_ACTION & (1 << c) != 0);
47552da9a59SGnoCiYeH             }
47652da9a59SGnoCiYeH         }
47752da9a59SGnoCiYeH 
47852da9a59SGnoCiYeH         if c == 127 && !self.display_ctrl {
47952da9a59SGnoCiYeH             return true;
48052da9a59SGnoCiYeH         }
48152da9a59SGnoCiYeH 
48252da9a59SGnoCiYeH         if c == 128 + 27 {
48352da9a59SGnoCiYeH             return true;
48452da9a59SGnoCiYeH         }
48552da9a59SGnoCiYeH 
48652da9a59SGnoCiYeH         false
48752da9a59SGnoCiYeH     }
48852da9a59SGnoCiYeH 
48952da9a59SGnoCiYeH     pub(super) fn set_cursor(&mut self) {
49052da9a59SGnoCiYeH         if self.mode == KDMode::KdGraphics {
49152da9a59SGnoCiYeH             return;
49252da9a59SGnoCiYeH         }
49352da9a59SGnoCiYeH 
49452da9a59SGnoCiYeH         if self.cursor_visible {
49552da9a59SGnoCiYeH             // TODO: 处理选择
49652da9a59SGnoCiYeH             self.add_softcursor();
49752da9a59SGnoCiYeH             if self.cursor_type.cursor_size() != VcCursor::CUR_NONE {
49852da9a59SGnoCiYeH                 self.driver_funcs().con_cursor(self, CursorOperation::Draw);
49952da9a59SGnoCiYeH             }
50052da9a59SGnoCiYeH         } else {
50152da9a59SGnoCiYeH             self.hide_cursor();
50252da9a59SGnoCiYeH         }
50352da9a59SGnoCiYeH     }
50452da9a59SGnoCiYeH 
50552da9a59SGnoCiYeH     /// ## 添加软光标
50652da9a59SGnoCiYeH     fn add_softcursor(&mut self) {
50752da9a59SGnoCiYeH         let mut i = self.screen_buf[self.pos] as u32;
50852da9a59SGnoCiYeH         let cursor_type = self.cursor_type;
50952da9a59SGnoCiYeH 
51052da9a59SGnoCiYeH         if !cursor_type.contains(VcCursor::CUR_SW) {
51152da9a59SGnoCiYeH             return;
51252da9a59SGnoCiYeH         }
51352da9a59SGnoCiYeH 
51452da9a59SGnoCiYeH         if SOFTCURSOR_ORIGINAL.read_irqsave().is_some() {
51552da9a59SGnoCiYeH             // 已经设置了软光标
51652da9a59SGnoCiYeH             return;
51752da9a59SGnoCiYeH         }
51852da9a59SGnoCiYeH 
51952da9a59SGnoCiYeH         let mut soft_cursor_guard = SOFTCURSOR_ORIGINAL.write_irqsave();
520b5b571e0SLoGin         *soft_cursor_guard = Some(unsafe { VcCursor::from_bits_unchecked(i) });
52152da9a59SGnoCiYeH 
52252da9a59SGnoCiYeH         let soft_cursor = soft_cursor_guard.unwrap();
52352da9a59SGnoCiYeH 
52452da9a59SGnoCiYeH         i |= cursor_type.cursor_set();
52552da9a59SGnoCiYeH         i ^= cursor_type.cursor_change();
52652da9a59SGnoCiYeH         if cursor_type.contains(VcCursor::CUR_ALWAYS_BG)
52752da9a59SGnoCiYeH             && ((soft_cursor.bits & VcCursor::CUR_BG.bits) == (i & VcCursor::CUR_BG.bits))
52852da9a59SGnoCiYeH         {
52952da9a59SGnoCiYeH             i ^= VcCursor::CUR_BG.bits;
53052da9a59SGnoCiYeH         }
53152da9a59SGnoCiYeH         if cursor_type.contains(VcCursor::CUR_INVERT_FG_BG)
53252da9a59SGnoCiYeH             && ((i & VcCursor::CUR_FG.bits) == ((i & VcCursor::CUR_BG.bits) >> 4))
53352da9a59SGnoCiYeH         {
53452da9a59SGnoCiYeH             i ^= VcCursor::CUR_FG.bits;
53552da9a59SGnoCiYeH         }
53652da9a59SGnoCiYeH 
53752da9a59SGnoCiYeH         self.screen_buf[self.pos] = i as u16;
53852da9a59SGnoCiYeH 
53952da9a59SGnoCiYeH         let _ =
54052da9a59SGnoCiYeH             self.driver_funcs()
541b5b571e0SLoGin                 .con_putc(self, i as u16, self.state.y as u32, self.state.x as u32);
54252da9a59SGnoCiYeH     }
54352da9a59SGnoCiYeH 
54452da9a59SGnoCiYeH     pub fn hide_cursor(&mut self) {
54552da9a59SGnoCiYeH         // TODO: 处理选择
54652da9a59SGnoCiYeH 
54752da9a59SGnoCiYeH         self.driver_funcs().con_cursor(self, CursorOperation::Erase);
54852da9a59SGnoCiYeH         self.hide_softcursor();
54952da9a59SGnoCiYeH     }
55052da9a59SGnoCiYeH 
55152da9a59SGnoCiYeH     fn hide_softcursor(&mut self) {
55252da9a59SGnoCiYeH         let softcursor = SOFTCURSOR_ORIGINAL.upgradeable_read_irqsave();
55352da9a59SGnoCiYeH         if softcursor.is_some() {
55452da9a59SGnoCiYeH             self.screen_buf[self.pos] = softcursor.unwrap().bits as u16;
55552da9a59SGnoCiYeH             let _ = self.driver_funcs().con_putc(
556b5b571e0SLoGin                 self,
55752da9a59SGnoCiYeH                 softcursor.unwrap().bits as u16,
55852da9a59SGnoCiYeH                 self.state.y as u32,
55952da9a59SGnoCiYeH                 self.state.x as u32,
56052da9a59SGnoCiYeH             );
56152da9a59SGnoCiYeH 
56252da9a59SGnoCiYeH             *softcursor.upgrade() = None;
56352da9a59SGnoCiYeH         }
56452da9a59SGnoCiYeH     }
56552da9a59SGnoCiYeH 
56652da9a59SGnoCiYeH     fn gotoxay(&mut self, x: i32, y: i32) {
56752da9a59SGnoCiYeH         if self.origin_mode {
56852da9a59SGnoCiYeH             self.gotoxy(x, self.top as i32 + y);
56952da9a59SGnoCiYeH         } else {
57052da9a59SGnoCiYeH             self.gotoxy(x, y)
57152da9a59SGnoCiYeH         }
57252da9a59SGnoCiYeH     }
57352da9a59SGnoCiYeH 
57452da9a59SGnoCiYeH     // ## 将当前vc的光标移动到目标位置
57552da9a59SGnoCiYeH     fn gotoxy(&mut self, x: i32, y: i32) {
57652da9a59SGnoCiYeH         if x < 0 {
57752da9a59SGnoCiYeH             self.state.x = 0;
578b5b571e0SLoGin         } else if x as usize >= self.cols {
57952da9a59SGnoCiYeH             self.state.x = self.cols - 1;
58052da9a59SGnoCiYeH         } else {
58152da9a59SGnoCiYeH             self.state.x = x as usize;
58252da9a59SGnoCiYeH         }
58352da9a59SGnoCiYeH 
58452da9a59SGnoCiYeH         let max_y;
58552da9a59SGnoCiYeH         let min_y;
58652da9a59SGnoCiYeH         if self.origin_mode {
58752da9a59SGnoCiYeH             min_y = self.top;
58852bcb59eSGnoCiYeH             max_y = self.bottom - 1;
58952da9a59SGnoCiYeH         } else {
59052da9a59SGnoCiYeH             min_y = 0;
59152bcb59eSGnoCiYeH             max_y = self.rows - 1;
59252da9a59SGnoCiYeH         }
59352da9a59SGnoCiYeH 
59452da9a59SGnoCiYeH         if y < min_y as i32 {
595b5b571e0SLoGin             self.state.y = min_y;
59652da9a59SGnoCiYeH         } else if y >= max_y as i32 {
597b5b571e0SLoGin             self.state.y = max_y;
59852da9a59SGnoCiYeH         } else {
59952da9a59SGnoCiYeH             self.state.y = y as usize;
60052da9a59SGnoCiYeH         }
60152da9a59SGnoCiYeH 
602be60c929SGnoCiYeH         self.pos = self.state.y * self.cols + self.state.x;
60352da9a59SGnoCiYeH         self.need_wrap = false;
60452da9a59SGnoCiYeH     }
60552da9a59SGnoCiYeH 
60652da9a59SGnoCiYeH     fn scroll(&mut self, dir: ScrollDir, mut nr: usize) {
60752da9a59SGnoCiYeH         // todo: uniscr_srceen
60852da9a59SGnoCiYeH         if self.top + nr >= self.bottom {
60952da9a59SGnoCiYeH             // 滚动超过一页,则按一页计算
61052da9a59SGnoCiYeH             nr = self.bottom - self.top - 1;
61152da9a59SGnoCiYeH         }
61252da9a59SGnoCiYeH 
61352da9a59SGnoCiYeH         if nr < 1 {
61452da9a59SGnoCiYeH             return;
61552da9a59SGnoCiYeH         }
61652da9a59SGnoCiYeH 
61752bcb59eSGnoCiYeH         if self.is_visible()
61852bcb59eSGnoCiYeH             && self
61952da9a59SGnoCiYeH                 .driver_funcs()
62052da9a59SGnoCiYeH                 .con_scroll(self, self.top, self.bottom, dir, nr)
62152da9a59SGnoCiYeH         {
62252da9a59SGnoCiYeH             // 如果成功
62352da9a59SGnoCiYeH             return;
62452da9a59SGnoCiYeH         }
62552da9a59SGnoCiYeH 
62652da9a59SGnoCiYeH         // 调整screen_buf
62752da9a59SGnoCiYeH         let count = nr * self.cols;
62852da9a59SGnoCiYeH         if dir == ScrollDir::Up {
62952da9a59SGnoCiYeH             for i in self.screen_buf[0..count].iter_mut() {
63052da9a59SGnoCiYeH                 *i = self.erase_char;
63152da9a59SGnoCiYeH             }
63252da9a59SGnoCiYeH             self.screen_buf.rotate_left(count);
63352da9a59SGnoCiYeH         } else if dir == ScrollDir::Down {
63452da9a59SGnoCiYeH             todo!();
63552da9a59SGnoCiYeH         }
63652da9a59SGnoCiYeH     }
63752da9a59SGnoCiYeH 
63852da9a59SGnoCiYeH     /// ## 退格
63952da9a59SGnoCiYeH     fn backspace(&mut self) {
64052da9a59SGnoCiYeH         if self.state.x > 0 {
64152da9a59SGnoCiYeH             self.pos -= 1;
64252da9a59SGnoCiYeH             self.state.x -= 1;
64352da9a59SGnoCiYeH             self.need_wrap = false;
64452da9a59SGnoCiYeH 
64552da9a59SGnoCiYeH             // TODO: notify
64652da9a59SGnoCiYeH         }
64752da9a59SGnoCiYeH     }
64852da9a59SGnoCiYeH 
64952da9a59SGnoCiYeH     /// ## 换行
65052da9a59SGnoCiYeH     fn line_feed(&mut self) {
651b5b571e0SLoGin         if self.state.y + 1 == self.bottom {
65252da9a59SGnoCiYeH             self.scroll(ScrollDir::Up, 1);
65352da9a59SGnoCiYeH         } else if self.state.y < self.rows - 1 {
65452da9a59SGnoCiYeH             self.state.y += 1;
65552da9a59SGnoCiYeH             self.pos += self.cols;
65652da9a59SGnoCiYeH         }
65752da9a59SGnoCiYeH 
65852da9a59SGnoCiYeH         self.need_wrap = false;
65952da9a59SGnoCiYeH         // TODO: Notify write
66052da9a59SGnoCiYeH     }
66152da9a59SGnoCiYeH 
66252da9a59SGnoCiYeH     /// ## 回车
66352da9a59SGnoCiYeH     fn carriage_return(&mut self) {
66452da9a59SGnoCiYeH         // 写入位置回退到该行最前
66552da9a59SGnoCiYeH         self.pos -= self.state.x;
66652da9a59SGnoCiYeH         self.need_wrap = false;
66752da9a59SGnoCiYeH         self.state.x = 0;
66852da9a59SGnoCiYeH     }
66952da9a59SGnoCiYeH 
67052da9a59SGnoCiYeH     /// ## Del
67152da9a59SGnoCiYeH     fn delete(&mut self) {
67252da9a59SGnoCiYeH         // ignore
67352da9a59SGnoCiYeH     }
67452da9a59SGnoCiYeH 
67552da9a59SGnoCiYeH     /// ## 向上滚动虚拟终端的内容,或者将光标上移一行
67652da9a59SGnoCiYeH     fn reverse_index(&mut self) {
677b5b571e0SLoGin         if self.state.y == self.top {
67852da9a59SGnoCiYeH             self.scroll(ScrollDir::Down, 1);
67952da9a59SGnoCiYeH         } else if self.state.y > 0 {
68052da9a59SGnoCiYeH             self.state.y -= 1;
68152da9a59SGnoCiYeH             self.pos -= self.cols;
68252da9a59SGnoCiYeH         }
68352da9a59SGnoCiYeH         self.need_wrap = false;
68452da9a59SGnoCiYeH     }
68552da9a59SGnoCiYeH 
68652da9a59SGnoCiYeH     /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#restore_cur
68752da9a59SGnoCiYeH     fn restore_cursor(&mut self) {
68852da9a59SGnoCiYeH         self.saved_state = self.state.clone();
68952da9a59SGnoCiYeH 
69052da9a59SGnoCiYeH         self.gotoxy(self.state.x as i32, self.state.y as i32);
69152da9a59SGnoCiYeH 
69252da9a59SGnoCiYeH         // TODO Gx_charset
69352da9a59SGnoCiYeH 
69452da9a59SGnoCiYeH         self.update_attr();
69552da9a59SGnoCiYeH         self.need_wrap = false;
69652da9a59SGnoCiYeH         todo!()
69752da9a59SGnoCiYeH     }
69852da9a59SGnoCiYeH 
69952da9a59SGnoCiYeH     /// ## 设置当前vt的各项属性
70052da9a59SGnoCiYeH     fn set_mode(&mut self, on_off: bool) {
70152da9a59SGnoCiYeH         for i in 0..self.npar as usize {
702b5b571e0SLoGin             if self.private == Vt102_OP::Pdec {
70352da9a59SGnoCiYeH                 match self.par[i] {
70452da9a59SGnoCiYeH                     1 => {
70552da9a59SGnoCiYeH                         todo!("kbd todo");
70652da9a59SGnoCiYeH                     }
70752da9a59SGnoCiYeH                     3 => {
70852da9a59SGnoCiYeH                         todo!("reisze todo");
70952da9a59SGnoCiYeH                     }
71052da9a59SGnoCiYeH                     5 => {
71152da9a59SGnoCiYeH                         todo!("invert_screen todo");
71252da9a59SGnoCiYeH                     }
71352da9a59SGnoCiYeH                     6 => {
71452da9a59SGnoCiYeH                         self.origin_mode = on_off;
71552da9a59SGnoCiYeH                         if on_off {
71652da9a59SGnoCiYeH                             self.gotoxy(0, self.top as i32);
71752da9a59SGnoCiYeH                         } else {
71852da9a59SGnoCiYeH                             self.gotoxy(0, 0);
71952da9a59SGnoCiYeH                         }
72052da9a59SGnoCiYeH                     }
72152da9a59SGnoCiYeH                     7 => {
72252da9a59SGnoCiYeH                         self.autowrap = on_off;
72352da9a59SGnoCiYeH                     }
72452da9a59SGnoCiYeH                     8 => {
72552da9a59SGnoCiYeH                         todo!("kbd todo");
72652da9a59SGnoCiYeH                     }
72752da9a59SGnoCiYeH                     9 => {
72852da9a59SGnoCiYeH                         todo!("report mouse todo");
72952da9a59SGnoCiYeH                     }
73052da9a59SGnoCiYeH                     25 => {
73152da9a59SGnoCiYeH                         self.cursor_visible = on_off;
73252da9a59SGnoCiYeH                     }
73352da9a59SGnoCiYeH                     1000 => {
73452da9a59SGnoCiYeH                         todo!("report mouse todo");
73552da9a59SGnoCiYeH                     }
73652da9a59SGnoCiYeH                     _ => {}
73752da9a59SGnoCiYeH                 }
73852da9a59SGnoCiYeH             } else {
73952da9a59SGnoCiYeH                 match self.par[i] {
74052da9a59SGnoCiYeH                     3 => {
74152da9a59SGnoCiYeH                         self.display_ctrl = on_off;
74252da9a59SGnoCiYeH                     }
74352da9a59SGnoCiYeH                     4 => {
74452da9a59SGnoCiYeH                         self.insert_mode = on_off;
74552da9a59SGnoCiYeH                     }
74652da9a59SGnoCiYeH                     20 => {
74752da9a59SGnoCiYeH                         todo!("kbd todo");
74852da9a59SGnoCiYeH                     }
74952da9a59SGnoCiYeH                     _ => {}
75052da9a59SGnoCiYeH                 }
75152da9a59SGnoCiYeH             }
75252da9a59SGnoCiYeH         }
75352da9a59SGnoCiYeH     }
75452da9a59SGnoCiYeH 
75552bcb59eSGnoCiYeH     #[inline(never)]
75652da9a59SGnoCiYeH     fn do_getpars(&mut self, c: char) {
75752da9a59SGnoCiYeH         if c == ';' && self.npar < (NPAR - 1) as u32 {
75852da9a59SGnoCiYeH             self.npar += 1;
75952da9a59SGnoCiYeH             return;
76052da9a59SGnoCiYeH         }
76152da9a59SGnoCiYeH 
762b5b571e0SLoGin         if c.is_ascii_digit() {
76352da9a59SGnoCiYeH             self.par[self.npar as usize] *= 10;
764b5b571e0SLoGin             self.par[self.npar as usize] += (c as u8 - b'0') as u32;
76552da9a59SGnoCiYeH             return;
76652da9a59SGnoCiYeH         }
76752da9a59SGnoCiYeH 
76852da9a59SGnoCiYeH         if c as u8 >= 0x20 && c as u8 <= 0x3f {
76952da9a59SGnoCiYeH             self.vc_state = VirtualConsoleState::EScsiignore;
77052da9a59SGnoCiYeH             return;
77152da9a59SGnoCiYeH         }
77252da9a59SGnoCiYeH 
77352da9a59SGnoCiYeH         self.vc_state = VirtualConsoleState::ESnormal;
77452da9a59SGnoCiYeH 
77552da9a59SGnoCiYeH         match c {
77652da9a59SGnoCiYeH             'h' => {
777b5b571e0SLoGin                 if self.private <= Vt102_OP::Pdec {
77852da9a59SGnoCiYeH                     self.set_mode(true);
77952da9a59SGnoCiYeH                 }
78052da9a59SGnoCiYeH                 return;
78152da9a59SGnoCiYeH             }
78252da9a59SGnoCiYeH             'l' => {
783b5b571e0SLoGin                 if self.private <= Vt102_OP::Pdec {
78452da9a59SGnoCiYeH                     self.set_mode(false);
78552da9a59SGnoCiYeH                 }
78652da9a59SGnoCiYeH                 return;
78752da9a59SGnoCiYeH             }
78852da9a59SGnoCiYeH             'c' => {
789b5b571e0SLoGin                 if self.private == Vt102_OP::Pdec {
79052da9a59SGnoCiYeH                     if self.par[0] != 0 {
79152da9a59SGnoCiYeH                         self.cursor_type =
79252da9a59SGnoCiYeH                             VcCursor::make_cursor(self.par[0], self.par[1], self.par[2])
79352da9a59SGnoCiYeH                     } else {
79452da9a59SGnoCiYeH                         self.cursor_type = VcCursor::CUR_UNDERLINE;
79552da9a59SGnoCiYeH                     }
79652da9a59SGnoCiYeH                     return;
79752da9a59SGnoCiYeH                 }
79852da9a59SGnoCiYeH             }
79952da9a59SGnoCiYeH             'm' => {
800b5b571e0SLoGin                 if self.private == Vt102_OP::Pdec {
80152da9a59SGnoCiYeH                     if self.par[0] != 0 {
80252da9a59SGnoCiYeH                         self.complement_mask = (self.par[0] << 8 | self.par[1]) as u16;
80352da9a59SGnoCiYeH                     } else {
80452da9a59SGnoCiYeH                         self.complement_mask = self.s_complement_mask;
80552da9a59SGnoCiYeH                     }
80652da9a59SGnoCiYeH                     return;
80752da9a59SGnoCiYeH                 }
80852da9a59SGnoCiYeH             }
80952da9a59SGnoCiYeH             'n' => {
810b5b571e0SLoGin                 if self.private == Vt102_OP::Pecma {
81152da9a59SGnoCiYeH                     if self.par[0] == 5 {
81252bcb59eSGnoCiYeH                         send_to_default_serial8250_port("tty status report todo".as_bytes());
81352bcb59eSGnoCiYeH                         panic!();
81452da9a59SGnoCiYeH                     } else if self.par[0] == 6 {
81552bcb59eSGnoCiYeH                         send_to_default_serial8250_port("tty cursor report todo".as_bytes());
81652bcb59eSGnoCiYeH                         panic!();
81752da9a59SGnoCiYeH                     }
81852da9a59SGnoCiYeH                 }
81952da9a59SGnoCiYeH                 return;
82052da9a59SGnoCiYeH             }
82152da9a59SGnoCiYeH             _ => {}
82252da9a59SGnoCiYeH         }
82352da9a59SGnoCiYeH 
824b5b571e0SLoGin         if self.private != Vt102_OP::Pecma {
825b5b571e0SLoGin             self.private = Vt102_OP::Pecma;
82652da9a59SGnoCiYeH             return;
82752da9a59SGnoCiYeH         }
82852da9a59SGnoCiYeH 
82952da9a59SGnoCiYeH         match c {
83052da9a59SGnoCiYeH             'G' | '`' => {
83152da9a59SGnoCiYeH                 if self.par[0] != 0 {
83252da9a59SGnoCiYeH                     self.par[0] -= 1;
83352da9a59SGnoCiYeH                 }
83452da9a59SGnoCiYeH                 self.gotoxy(self.par[0] as i32, self.state.y as i32);
83552da9a59SGnoCiYeH                 return;
83652da9a59SGnoCiYeH             }
83752da9a59SGnoCiYeH             'A' => {
83852da9a59SGnoCiYeH                 if self.par[0] == 0 {
83952da9a59SGnoCiYeH                     self.par[0] += 1;
84052da9a59SGnoCiYeH                 }
84152da9a59SGnoCiYeH                 self.gotoxy(
84252da9a59SGnoCiYeH                     self.state.x as i32,
84352da9a59SGnoCiYeH                     (self.state.y - self.par[0] as usize) as i32,
84452da9a59SGnoCiYeH                 );
84552da9a59SGnoCiYeH                 return;
84652da9a59SGnoCiYeH             }
84752da9a59SGnoCiYeH             'B' | 'e' => {
84852da9a59SGnoCiYeH                 if self.par[0] == 0 {
84952da9a59SGnoCiYeH                     self.par[0] += 1;
85052da9a59SGnoCiYeH                 }
85152da9a59SGnoCiYeH                 self.gotoxy(
85252da9a59SGnoCiYeH                     self.state.x as i32,
85352da9a59SGnoCiYeH                     (self.state.y + self.par[0] as usize) as i32,
85452da9a59SGnoCiYeH                 );
85552da9a59SGnoCiYeH                 return;
85652da9a59SGnoCiYeH             }
85752da9a59SGnoCiYeH             'C' | 'a' => {
85852da9a59SGnoCiYeH                 if self.par[0] == 0 {
85952da9a59SGnoCiYeH                     self.par[0] += 1;
86052da9a59SGnoCiYeH                 }
86152da9a59SGnoCiYeH                 self.gotoxy(
86252da9a59SGnoCiYeH                     (self.state.x + self.par[0] as usize) as i32,
86352da9a59SGnoCiYeH                     self.state.y as i32,
86452da9a59SGnoCiYeH                 );
86552da9a59SGnoCiYeH                 return;
86652da9a59SGnoCiYeH             }
86752da9a59SGnoCiYeH             'D' => {
86852da9a59SGnoCiYeH                 if self.par[0] == 0 {
86952da9a59SGnoCiYeH                     self.par[0] += 1;
87052da9a59SGnoCiYeH                 }
87152da9a59SGnoCiYeH                 self.gotoxy(
87252bcb59eSGnoCiYeH                     self.state.x as i32 - self.par[0] as i32,
87352da9a59SGnoCiYeH                     self.state.y as i32,
87452da9a59SGnoCiYeH                 );
87552da9a59SGnoCiYeH                 return;
87652da9a59SGnoCiYeH             }
87752da9a59SGnoCiYeH             'E' => {
87852da9a59SGnoCiYeH                 if self.par[0] == 0 {
87952da9a59SGnoCiYeH                     self.par[0] += 1;
88052da9a59SGnoCiYeH                 }
88152da9a59SGnoCiYeH                 self.gotoxy(0, (self.state.y + self.par[0] as usize) as i32);
88252da9a59SGnoCiYeH                 return;
88352da9a59SGnoCiYeH             }
88452da9a59SGnoCiYeH             'F' => {
88552da9a59SGnoCiYeH                 if self.par[0] == 0 {
88652da9a59SGnoCiYeH                     self.par[0] += 1;
88752da9a59SGnoCiYeH                 }
88852bcb59eSGnoCiYeH                 self.gotoxy(0, self.state.y as i32 - self.par[0] as i32);
88952da9a59SGnoCiYeH                 return;
89052da9a59SGnoCiYeH             }
89152da9a59SGnoCiYeH             'd' => {
89252da9a59SGnoCiYeH                 if self.par[0] != 0 {
89352da9a59SGnoCiYeH                     self.par[0] -= 1;
89452da9a59SGnoCiYeH                 }
89552da9a59SGnoCiYeH                 self.gotoxay(self.state.x as i32, self.par[0] as i32);
89652da9a59SGnoCiYeH                 return;
89752da9a59SGnoCiYeH             }
89852da9a59SGnoCiYeH             'H' | 'f' => {
89952bcb59eSGnoCiYeH                 // MOVETO
90052da9a59SGnoCiYeH                 if self.par[0] != 0 {
90152da9a59SGnoCiYeH                     self.par[0] -= 1;
90252da9a59SGnoCiYeH                 }
90352da9a59SGnoCiYeH                 if self.par[1] != 0 {
90452da9a59SGnoCiYeH                     self.par[1] -= 1;
90552da9a59SGnoCiYeH                 }
90652da9a59SGnoCiYeH                 self.gotoxay(self.par[1] as i32, self.par[0] as i32);
90752da9a59SGnoCiYeH                 return;
90852da9a59SGnoCiYeH             }
90952da9a59SGnoCiYeH             'J' => {
91052da9a59SGnoCiYeH                 self.csi_J(self.par[0]);
91152da9a59SGnoCiYeH                 return;
91252da9a59SGnoCiYeH             }
91352da9a59SGnoCiYeH             'K' => {
91452da9a59SGnoCiYeH                 self.csi_K(self.par[0]);
91552da9a59SGnoCiYeH                 return;
91652da9a59SGnoCiYeH             }
91752da9a59SGnoCiYeH             'L' => {
91852da9a59SGnoCiYeH                 todo!("csi_L todo");
91952da9a59SGnoCiYeH             }
92052da9a59SGnoCiYeH             'M' => {
92152da9a59SGnoCiYeH                 todo!("csi_M todo");
92252da9a59SGnoCiYeH             }
92352da9a59SGnoCiYeH             'P' => {
92452da9a59SGnoCiYeH                 todo!("csi_P todo");
92552da9a59SGnoCiYeH             }
92652bcb59eSGnoCiYeH 
92752bcb59eSGnoCiYeH             // 非ANSI标准,为ANSI拓展
92852bcb59eSGnoCiYeH             'S' => {
92952bcb59eSGnoCiYeH                 self.scroll(ScrollDir::Up, self.par[0] as usize);
93052bcb59eSGnoCiYeH                 return;
93152bcb59eSGnoCiYeH             }
93252bcb59eSGnoCiYeH 
93352bcb59eSGnoCiYeH             'T' => {
93452bcb59eSGnoCiYeH                 self.scroll(ScrollDir::Down, self.par[0] as usize);
93552bcb59eSGnoCiYeH                 return;
93652bcb59eSGnoCiYeH             }
93752bcb59eSGnoCiYeH 
93852da9a59SGnoCiYeH             'c' => {
93952da9a59SGnoCiYeH                 if self.par[0] == 0 {
94052da9a59SGnoCiYeH                     kwarn!("respone ID todo");
94152da9a59SGnoCiYeH                 }
94252da9a59SGnoCiYeH                 return;
94352da9a59SGnoCiYeH             }
94452da9a59SGnoCiYeH             'g' => {
94552da9a59SGnoCiYeH                 if self.par[0] == 0 && self.state.x < 256 {
946b5b571e0SLoGin                     self.tab_stop.set(self.state.x, true);
94752da9a59SGnoCiYeH                 } else if self.par[0] == 3 {
94852da9a59SGnoCiYeH                     self.tab_stop.set_all(false);
94952da9a59SGnoCiYeH                 }
95052da9a59SGnoCiYeH                 return;
95152da9a59SGnoCiYeH             }
95252da9a59SGnoCiYeH             'm' => {
95352da9a59SGnoCiYeH                 self.csi_m();
95452da9a59SGnoCiYeH                 return;
95552da9a59SGnoCiYeH             }
95652da9a59SGnoCiYeH             'q' => {
95752da9a59SGnoCiYeH                 if self.par[0] < 4 {
95852da9a59SGnoCiYeH                     todo!("vt set led state todo");
95952da9a59SGnoCiYeH                 }
96052da9a59SGnoCiYeH                 return;
96152da9a59SGnoCiYeH             }
96252da9a59SGnoCiYeH             'r' => {
96352da9a59SGnoCiYeH                 if self.par[0] == 0 {
96452da9a59SGnoCiYeH                     self.par[0] += 1;
96552da9a59SGnoCiYeH                 }
96652da9a59SGnoCiYeH                 if self.par[1] == 0 {
96752da9a59SGnoCiYeH                     self.par[1] = self.rows as u32;
96852da9a59SGnoCiYeH                 }
96952da9a59SGnoCiYeH                 if self.par[0] < self.par[1] && self.par[1] <= self.rows as u32 {
97052da9a59SGnoCiYeH                     self.top = self.par[0] as usize - 1;
97152da9a59SGnoCiYeH                     self.bottom = self.par[1] as usize;
97252da9a59SGnoCiYeH                     self.gotoxay(0, 0);
97352da9a59SGnoCiYeH                 }
97452da9a59SGnoCiYeH                 return;
97552da9a59SGnoCiYeH             }
97652da9a59SGnoCiYeH             's' => {
97752da9a59SGnoCiYeH                 self.saved_state = self.state.clone();
97852da9a59SGnoCiYeH                 return;
97952da9a59SGnoCiYeH             }
98052da9a59SGnoCiYeH             'u' => {
98152da9a59SGnoCiYeH                 self.restore_cursor();
98252da9a59SGnoCiYeH                 return;
98352da9a59SGnoCiYeH             }
98452da9a59SGnoCiYeH             '@' => {
98552da9a59SGnoCiYeH                 todo!("csi_at todo");
98652da9a59SGnoCiYeH             }
98752da9a59SGnoCiYeH             ']' => {
98852da9a59SGnoCiYeH                 todo!("set termial command todo");
98952da9a59SGnoCiYeH             }
99052da9a59SGnoCiYeH             _ => {}
99152da9a59SGnoCiYeH         }
99252da9a59SGnoCiYeH     }
99352da9a59SGnoCiYeH 
99452da9a59SGnoCiYeH     /// ##  处理Control Sequence Introducer(控制序列引导符) m字符
99552bcb59eSGnoCiYeH     #[inline(never)]
99652da9a59SGnoCiYeH     fn csi_m(&mut self) {
99752da9a59SGnoCiYeH         let mut i = 0;
99852da9a59SGnoCiYeH         loop {
99952da9a59SGnoCiYeH             if i > self.npar as usize {
100052da9a59SGnoCiYeH                 break;
100152da9a59SGnoCiYeH             }
100252da9a59SGnoCiYeH             match self.par[i] {
100352da9a59SGnoCiYeH                 0 => {
100452da9a59SGnoCiYeH                     // 关闭所有属性
100552da9a59SGnoCiYeH                     self.default_attr();
100652da9a59SGnoCiYeH                 }
100752da9a59SGnoCiYeH 
100852da9a59SGnoCiYeH                 1 => {
100952da9a59SGnoCiYeH                     // 设置粗体
1010b5b571e0SLoGin                     self.state.intensity = VirtualConsoleIntensity::Bold;
101152da9a59SGnoCiYeH                 }
101252da9a59SGnoCiYeH 
101352da9a59SGnoCiYeH                 2 => {
101452da9a59SGnoCiYeH                     // 设置半亮度(半明显
1015b5b571e0SLoGin                     self.state.intensity = VirtualConsoleIntensity::HalfBright;
101652da9a59SGnoCiYeH                 }
101752da9a59SGnoCiYeH 
101852da9a59SGnoCiYeH                 3 => {
101952da9a59SGnoCiYeH                     // 斜体
102052da9a59SGnoCiYeH                     self.state.italic = true;
102152da9a59SGnoCiYeH                 }
102252da9a59SGnoCiYeH 
102352da9a59SGnoCiYeH                 4 | 21 => {
102452da9a59SGnoCiYeH                     // 下划线
102552da9a59SGnoCiYeH 
102652da9a59SGnoCiYeH                     // 21是设置双下划线,但是不支持,就单下划线
102752da9a59SGnoCiYeH                     self.state.underline = true;
102852da9a59SGnoCiYeH                 }
102952da9a59SGnoCiYeH 
103052da9a59SGnoCiYeH                 5 => {
103152da9a59SGnoCiYeH                     // 设置闪烁
103252da9a59SGnoCiYeH                     self.state.blink = true;
103352da9a59SGnoCiYeH                 }
103452da9a59SGnoCiYeH 
103552da9a59SGnoCiYeH                 7 => {
103652da9a59SGnoCiYeH                     // 设置反显(前景色与背景色对调)
103752da9a59SGnoCiYeH                     self.state.reverse = true;
103852da9a59SGnoCiYeH                 }
103952da9a59SGnoCiYeH 
104052da9a59SGnoCiYeH                 10 => {
104152da9a59SGnoCiYeH                     // 选择主要字体
104252da9a59SGnoCiYeH                     todo!()
104352da9a59SGnoCiYeH                 }
104452da9a59SGnoCiYeH 
104552da9a59SGnoCiYeH                 11 => {
104652da9a59SGnoCiYeH                     // 选择第一个替代字体
104752da9a59SGnoCiYeH                     todo!()
104852da9a59SGnoCiYeH                 }
104952da9a59SGnoCiYeH 
105052da9a59SGnoCiYeH                 12 => {
105152da9a59SGnoCiYeH                     // 选择第二个替代字体
105252da9a59SGnoCiYeH                     todo!()
105352da9a59SGnoCiYeH                 }
105452da9a59SGnoCiYeH 
105552da9a59SGnoCiYeH                 22 => {
105652da9a59SGnoCiYeH                     //  关闭粗体和半亮度,恢复正常亮度
1057b5b571e0SLoGin                     self.state.intensity = VirtualConsoleIntensity::Normal;
105852da9a59SGnoCiYeH                 }
105952da9a59SGnoCiYeH 
106052da9a59SGnoCiYeH                 23 => {
106152da9a59SGnoCiYeH                     // 关闭斜体
106252da9a59SGnoCiYeH                     self.state.italic = false;
106352da9a59SGnoCiYeH                 }
106452da9a59SGnoCiYeH 
106552da9a59SGnoCiYeH                 24 => {
106652da9a59SGnoCiYeH                     // 关闭下划线
106752da9a59SGnoCiYeH                     self.state.underline = false;
106852da9a59SGnoCiYeH                 }
106952da9a59SGnoCiYeH 
107052da9a59SGnoCiYeH                 25 => {
107152da9a59SGnoCiYeH                     // 关闭字符闪烁
107252da9a59SGnoCiYeH                     self.state.blink = false;
107352da9a59SGnoCiYeH                 }
107452da9a59SGnoCiYeH 
107552da9a59SGnoCiYeH                 27 => {
107652da9a59SGnoCiYeH                     // 关闭反显
107752da9a59SGnoCiYeH                     self.state.reverse = false;
107852da9a59SGnoCiYeH                 }
107952da9a59SGnoCiYeH 
108052da9a59SGnoCiYeH                 38 => {
108152da9a59SGnoCiYeH                     // 设置前景色
108252da9a59SGnoCiYeH                     let (idx, color) = self.t416_color(i);
108352da9a59SGnoCiYeH                     i = idx;
1084b5b571e0SLoGin                     if let Some(color) = color {
108552da9a59SGnoCiYeH                         let mut max = color.red.max(color.green);
108652da9a59SGnoCiYeH                         max = max.max(color.blue);
108752da9a59SGnoCiYeH 
108852da9a59SGnoCiYeH                         let mut hue = 0;
108952da9a59SGnoCiYeH                         if color.red > max / 2 {
109052da9a59SGnoCiYeH                             hue |= 4;
109152da9a59SGnoCiYeH                         }
109252da9a59SGnoCiYeH                         if color.green > max / 2 {
109352da9a59SGnoCiYeH                             hue |= 2;
109452da9a59SGnoCiYeH                         }
109552da9a59SGnoCiYeH                         if color.blue > max / 2 {
109652da9a59SGnoCiYeH                             hue |= 1;
109752da9a59SGnoCiYeH                         }
109852da9a59SGnoCiYeH 
109952da9a59SGnoCiYeH                         if hue == 7 && max <= 0x55 {
110052da9a59SGnoCiYeH                             hue = 0;
1101b5b571e0SLoGin                             self.state.intensity = VirtualConsoleIntensity::Bold;
110252da9a59SGnoCiYeH                         } else if max > 0xaa {
1103b5b571e0SLoGin                             self.state.intensity = VirtualConsoleIntensity::Bold;
110452da9a59SGnoCiYeH                         } else {
1105b5b571e0SLoGin                             self.state.intensity = VirtualConsoleIntensity::Normal;
110652da9a59SGnoCiYeH                         }
110752da9a59SGnoCiYeH 
110852da9a59SGnoCiYeH                         self.state.color = (self.state.color & 0xf0) | hue;
110952da9a59SGnoCiYeH                     }
111052da9a59SGnoCiYeH                 }
111152da9a59SGnoCiYeH 
111252da9a59SGnoCiYeH                 48 => {
111352da9a59SGnoCiYeH                     // 设置背景色
111452da9a59SGnoCiYeH                     let (idx, color) = self.t416_color(i);
111552da9a59SGnoCiYeH                     i = idx;
1116b5b571e0SLoGin                     if let Some(color) = color {
111752da9a59SGnoCiYeH                         self.state.color = (self.state.color & 0x0f)
111852da9a59SGnoCiYeH                             | ((color.red as u8 & 0x80) >> 1)
111952da9a59SGnoCiYeH                             | ((color.green as u8 & 0x80) >> 2)
112052da9a59SGnoCiYeH                             | ((color.blue as u8 & 0x80) >> 3);
112152da9a59SGnoCiYeH                     }
112252da9a59SGnoCiYeH                 }
112352da9a59SGnoCiYeH 
112452da9a59SGnoCiYeH                 39 => {
112552da9a59SGnoCiYeH                     // 恢复默认前景色
112652da9a59SGnoCiYeH                     self.state.color = (self.def_color & 0x0f) | (self.state.color & 0xf0);
112752da9a59SGnoCiYeH                 }
112852da9a59SGnoCiYeH 
112952da9a59SGnoCiYeH                 49 => {
113052da9a59SGnoCiYeH                     // 恢复默认背景色
113152da9a59SGnoCiYeH                     self.state.color = (self.def_color & 0xf0) | (self.state.color & 0x0f);
113252da9a59SGnoCiYeH                 }
113352da9a59SGnoCiYeH 
113452da9a59SGnoCiYeH                 _ => {
113552da9a59SGnoCiYeH                     if self.par[i] >= 90 && self.par[i] <= 107 {
113652da9a59SGnoCiYeH                         if self.par[i] < 100 {
1137b5b571e0SLoGin                             self.state.intensity = VirtualConsoleIntensity::Bold;
113852da9a59SGnoCiYeH                         }
113952da9a59SGnoCiYeH                         self.par[i] -= 60;
114052da9a59SGnoCiYeH                     }
114152da9a59SGnoCiYeH 
114252da9a59SGnoCiYeH                     if self.par[i] >= 30 && self.par[i] <= 37 {
114352da9a59SGnoCiYeH                         self.state.color =
114452da9a59SGnoCiYeH                             COLOR_TABLE[self.par[i] as usize - 30] | self.state.color & 0xf0;
114552da9a59SGnoCiYeH                     } else if self.par[i] >= 40 && self.par[i] <= 47 {
114652da9a59SGnoCiYeH                         self.state.color =
114752da9a59SGnoCiYeH                             (COLOR_TABLE[self.par[i] as usize - 40] << 4) | self.state.color & 0xf0;
114852da9a59SGnoCiYeH                     }
114952da9a59SGnoCiYeH                 }
115052da9a59SGnoCiYeH             }
115152da9a59SGnoCiYeH 
115252da9a59SGnoCiYeH             i += 1;
115352da9a59SGnoCiYeH         }
115452da9a59SGnoCiYeH 
115552da9a59SGnoCiYeH         self.update_attr();
115652da9a59SGnoCiYeH     }
115752da9a59SGnoCiYeH 
115852da9a59SGnoCiYeH     /// ##  处理Control Sequence Introducer(控制序列引导符) J字符
115952da9a59SGnoCiYeH     /// 该命令用于擦除终端显示区域的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作:
116052da9a59SGnoCiYeH     /// - vpar 为 0 时,擦除从光标位置到显示区域末尾的内容;
116152da9a59SGnoCiYeH     /// - vpar 为 1 时,擦除从显示区域起始位置到光标位置的内容;
116252da9a59SGnoCiYeH     /// - vpar 为 2 或 3 时,分别表示擦除整个显示区域的内容,其中参数 3 还会清除回滚缓冲区的内容。
116352da9a59SGnoCiYeH     #[allow(non_snake_case)]
116452da9a59SGnoCiYeH     fn csi_J(&mut self, vpar: u32) {
116552da9a59SGnoCiYeH         let count;
116652da9a59SGnoCiYeH         let start;
116752da9a59SGnoCiYeH 
116852da9a59SGnoCiYeH         match vpar {
116952da9a59SGnoCiYeH             0 => {
117052da9a59SGnoCiYeH                 // 擦除从光标位置到显示区域末尾的内容
117152da9a59SGnoCiYeH                 count = self.screen_buf.len() - self.pos;
117252da9a59SGnoCiYeH                 start = self.pos;
117352da9a59SGnoCiYeH             }
117452da9a59SGnoCiYeH             1 => {
117552da9a59SGnoCiYeH                 // 擦除从显示区域起始位置到光标位置的内容
117652da9a59SGnoCiYeH                 count = self.pos;
117752da9a59SGnoCiYeH                 start = 0;
117852da9a59SGnoCiYeH             }
117952da9a59SGnoCiYeH             2 => {
118052da9a59SGnoCiYeH                 // 擦除整个显示区域的内容
118152da9a59SGnoCiYeH                 count = self.screen_buf.len();
118252da9a59SGnoCiYeH                 start = 0;
118352da9a59SGnoCiYeH             }
118452da9a59SGnoCiYeH             3 => {
118552da9a59SGnoCiYeH                 // 表示擦除整个显示区域的内容,还会清除回滚缓冲区的内容
118652da9a59SGnoCiYeH                 // TODO:当前未实现回滚缓冲
118752da9a59SGnoCiYeH                 count = self.screen_buf.len();
118852da9a59SGnoCiYeH                 start = 0;
118952da9a59SGnoCiYeH             }
119052da9a59SGnoCiYeH             _ => {
119152da9a59SGnoCiYeH                 return;
119252da9a59SGnoCiYeH             }
119352da9a59SGnoCiYeH         }
119452da9a59SGnoCiYeH 
119552da9a59SGnoCiYeH         for i in self.screen_buf[start..(start + count)].iter_mut() {
119652da9a59SGnoCiYeH             *i = self.erase_char;
119752da9a59SGnoCiYeH         }
119852da9a59SGnoCiYeH 
119952da9a59SGnoCiYeH         if self.should_update() {
120052da9a59SGnoCiYeH             self.do_update_region(start, count)
120152da9a59SGnoCiYeH         }
120252da9a59SGnoCiYeH 
120352da9a59SGnoCiYeH         self.need_wrap = false;
120452da9a59SGnoCiYeH     }
120552da9a59SGnoCiYeH 
120652da9a59SGnoCiYeH     /// ##  处理Control Sequence Introducer(控制序列引导符) K字符
120752da9a59SGnoCiYeH     /// 该命令用于擦除终端当前行的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作:
120852da9a59SGnoCiYeH     /// - vpar 为 0 时,擦除从光标位置到该行末尾的内容
120952da9a59SGnoCiYeH     /// - vpar 为 1 时,擦除从该行起始位置到光标位置的内容
121052da9a59SGnoCiYeH     /// - vpar 为 2 时,擦除整个行。
121152da9a59SGnoCiYeH     #[allow(non_snake_case)]
121252da9a59SGnoCiYeH     fn csi_K(&mut self, vpar: u32) {
121352da9a59SGnoCiYeH         let count;
121452da9a59SGnoCiYeH         let start;
121552da9a59SGnoCiYeH 
121652da9a59SGnoCiYeH         match vpar {
121752da9a59SGnoCiYeH             0 => {
121852da9a59SGnoCiYeH                 // 擦除从光标位置到该行末尾的内容
121952da9a59SGnoCiYeH                 count = self.cols - self.state.x;
122052da9a59SGnoCiYeH                 start = self.pos;
122152da9a59SGnoCiYeH             }
122252da9a59SGnoCiYeH             1 => {
122352da9a59SGnoCiYeH                 // 擦除从该行起始位置到光标位置的内容
122452da9a59SGnoCiYeH                 count = self.state.x + 1;
122552da9a59SGnoCiYeH                 start = self.pos - self.state.x;
122652da9a59SGnoCiYeH             }
122752da9a59SGnoCiYeH             2 => {
122852da9a59SGnoCiYeH                 // 擦除整个行
122952da9a59SGnoCiYeH                 count = self.cols;
123052da9a59SGnoCiYeH                 start = self.pos - self.state.x;
123152da9a59SGnoCiYeH             }
123252da9a59SGnoCiYeH             _ => {
123352da9a59SGnoCiYeH                 return;
123452da9a59SGnoCiYeH             }
123552da9a59SGnoCiYeH         }
123652da9a59SGnoCiYeH 
1237be60c929SGnoCiYeH         let max_idx = self.screen_buf.len();
1238be60c929SGnoCiYeH         for i in self.screen_buf[start..max_idx.min(start + count)].iter_mut() {
123952da9a59SGnoCiYeH             *i = self.erase_char;
124052da9a59SGnoCiYeH         }
124152da9a59SGnoCiYeH 
124252da9a59SGnoCiYeH         if self.should_update() {
1243be60c929SGnoCiYeH             self.do_update_region(start, count.min(max_idx - start))
124452da9a59SGnoCiYeH         }
124552da9a59SGnoCiYeH 
124652da9a59SGnoCiYeH         self.need_wrap = false;
124752da9a59SGnoCiYeH     }
124852da9a59SGnoCiYeH 
124952da9a59SGnoCiYeH     fn t416_color(&mut self, mut idx: usize) -> (usize, Option<Color>) {
125052da9a59SGnoCiYeH         idx += 1;
125152da9a59SGnoCiYeH         if idx > self.npar as usize {
125252da9a59SGnoCiYeH             return (idx, None);
125352da9a59SGnoCiYeH         }
125452da9a59SGnoCiYeH 
1255b5b571e0SLoGin         if self.par[idx] == 5 && idx < self.npar as usize {
125652da9a59SGnoCiYeH             // 256色
125752da9a59SGnoCiYeH             idx += 1;
125852da9a59SGnoCiYeH             return (idx, Some(Color::from_256(self.par[idx])));
125952da9a59SGnoCiYeH         } else if self.par[idx] == 2 && idx + 3 <= self.npar as usize {
126052da9a59SGnoCiYeH             // 24位
1261b5b571e0SLoGin             let color = Color {
1262b5b571e0SLoGin                 red: self.par[idx + 1] as u16,
1263b5b571e0SLoGin                 green: self.par[idx + 2] as u16,
1264b5b571e0SLoGin                 blue: self.par[idx + 3] as u16,
1265b5b571e0SLoGin                 ..Default::default()
1266b5b571e0SLoGin             };
126752da9a59SGnoCiYeH             idx += 3;
126852da9a59SGnoCiYeH             return (idx, Some(color));
126952da9a59SGnoCiYeH         } else {
127052da9a59SGnoCiYeH             return (idx, None);
127152da9a59SGnoCiYeH         }
127252da9a59SGnoCiYeH     }
127352da9a59SGnoCiYeH 
127452da9a59SGnoCiYeH     /// ## 处理终端控制字符
127552bcb59eSGnoCiYeH     #[inline(never)]
127652da9a59SGnoCiYeH     pub(super) fn do_control(&mut self, ch: u32) {
127752da9a59SGnoCiYeH         // 首先检查是否处于 ANSI 控制字符串状态
1278b5b571e0SLoGin         if self.vc_state.is_ansi_control_string() && (8..=13).contains(&ch) {
127952da9a59SGnoCiYeH             return;
128052da9a59SGnoCiYeH         }
128152da9a59SGnoCiYeH 
128252da9a59SGnoCiYeH         match ch {
128352da9a59SGnoCiYeH             0 => {
128452da9a59SGnoCiYeH                 return;
128552da9a59SGnoCiYeH             }
128652da9a59SGnoCiYeH             7 => {
128752da9a59SGnoCiYeH                 // BEL
128852da9a59SGnoCiYeH                 if self.vc_state.is_ansi_control_string() {
128952da9a59SGnoCiYeH                     self.vc_state = VirtualConsoleState::ESnormal;
129052da9a59SGnoCiYeH                 }
129152da9a59SGnoCiYeH                 // TODO: 发出声音?
129252da9a59SGnoCiYeH                 return;
129352da9a59SGnoCiYeH             }
129452da9a59SGnoCiYeH             8 => {
129552da9a59SGnoCiYeH                 // BS backspace
129652da9a59SGnoCiYeH                 self.backspace();
129752da9a59SGnoCiYeH                 return;
129852da9a59SGnoCiYeH             }
129952da9a59SGnoCiYeH             9 => {
130052da9a59SGnoCiYeH                 // 水平制表符(Horizontal Tab)
130152da9a59SGnoCiYeH                 self.pos -= self.state.x;
130252da9a59SGnoCiYeH 
130352da9a59SGnoCiYeH                 let ret = self.tab_stop.next_index(self.state.x + 1);
130452da9a59SGnoCiYeH 
1305b5b571e0SLoGin                 if let Some(x) = ret {
1306b5b571e0SLoGin                     self.state.x = x;
130752da9a59SGnoCiYeH                 } else {
1308b5b571e0SLoGin                     self.state.x = self.cols - 1;
130952da9a59SGnoCiYeH                 }
131052da9a59SGnoCiYeH 
131152da9a59SGnoCiYeH                 self.pos += self.state.x;
131252da9a59SGnoCiYeH                 // TODO: notify
131352da9a59SGnoCiYeH                 return;
131452da9a59SGnoCiYeH             }
1315b5b571e0SLoGin             10..=12 => {
131652da9a59SGnoCiYeH                 // LD line feed
131752da9a59SGnoCiYeH                 self.line_feed();
131852da9a59SGnoCiYeH                 // TODO: 检查键盘模式
131952da9a59SGnoCiYeH                 self.carriage_return();
132052da9a59SGnoCiYeH                 return;
132152da9a59SGnoCiYeH             }
132252da9a59SGnoCiYeH             13 => {
132352da9a59SGnoCiYeH                 // CR 回车符
132452da9a59SGnoCiYeH                 self.carriage_return();
132552da9a59SGnoCiYeH                 return;
132652da9a59SGnoCiYeH             }
132752da9a59SGnoCiYeH             14 => {
132852da9a59SGnoCiYeH                 todo!("Gx_charset todo!");
132952da9a59SGnoCiYeH             }
133052da9a59SGnoCiYeH             15 => {
133152da9a59SGnoCiYeH                 todo!("Gx_charset todo!");
133252da9a59SGnoCiYeH             }
133352da9a59SGnoCiYeH             24 | 26 => {
133452da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESnormal;
133552da9a59SGnoCiYeH                 return;
133652da9a59SGnoCiYeH             }
133752da9a59SGnoCiYeH             27 => {
133852da9a59SGnoCiYeH                 // esc
133952da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESesc;
134052da9a59SGnoCiYeH                 return;
134152da9a59SGnoCiYeH             }
134252da9a59SGnoCiYeH             127 => {
134352da9a59SGnoCiYeH                 // delete
134452da9a59SGnoCiYeH                 self.delete();
134552da9a59SGnoCiYeH                 return;
134652da9a59SGnoCiYeH             }
134752da9a59SGnoCiYeH             155 => {
134852da9a59SGnoCiYeH                 // '['
134952da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESsquare;
135052da9a59SGnoCiYeH                 return;
135152da9a59SGnoCiYeH             }
135252da9a59SGnoCiYeH             _ => {}
135352da9a59SGnoCiYeH         }
135452da9a59SGnoCiYeH 
135552da9a59SGnoCiYeH         match self.vc_state {
135652da9a59SGnoCiYeH             VirtualConsoleState::ESesc => {
135752da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESnormal;
135852da9a59SGnoCiYeH                 match ch as u8 as char {
135952da9a59SGnoCiYeH                     '[' => {
136052da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESsquare;
136152da9a59SGnoCiYeH                     }
136252da9a59SGnoCiYeH                     ']' => {
136352da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESnonstd;
136452da9a59SGnoCiYeH                     }
136552da9a59SGnoCiYeH                     '_' => {
136652da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESapc;
136752da9a59SGnoCiYeH                     }
136852da9a59SGnoCiYeH                     '^' => {
136952da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESpm;
137052da9a59SGnoCiYeH                     }
137152da9a59SGnoCiYeH                     '%' => {
137252da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESpercent;
137352da9a59SGnoCiYeH                     }
137452da9a59SGnoCiYeH                     'E' => {
137552da9a59SGnoCiYeH                         self.carriage_return();
137652da9a59SGnoCiYeH                         self.line_feed();
137752da9a59SGnoCiYeH                     }
137852da9a59SGnoCiYeH                     'M' => {
137952da9a59SGnoCiYeH                         self.reverse_index();
138052da9a59SGnoCiYeH                     }
138152da9a59SGnoCiYeH                     'D' => {
138252da9a59SGnoCiYeH                         self.line_feed();
138352da9a59SGnoCiYeH                     }
138452da9a59SGnoCiYeH                     'H' => {
138552da9a59SGnoCiYeH                         if self.state.x < 256 {
138652da9a59SGnoCiYeH                             self.tab_stop.set(self.state.x, true);
138752da9a59SGnoCiYeH                         }
138852da9a59SGnoCiYeH                     }
138952da9a59SGnoCiYeH                     'P' => {
139052da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESdcs;
139152da9a59SGnoCiYeH                     }
139252da9a59SGnoCiYeH                     'Z' => {
139352da9a59SGnoCiYeH                         todo!("Respond ID todo!");
139452da9a59SGnoCiYeH                     }
139552da9a59SGnoCiYeH                     '7' => self.saved_state = self.state.clone(),
139652da9a59SGnoCiYeH                     '8' => self.restore_cursor(),
139752da9a59SGnoCiYeH                     '(' => {
139852da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESsetG0;
139952da9a59SGnoCiYeH                     }
140052da9a59SGnoCiYeH                     ')' => {
140152da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESsetG1;
140252da9a59SGnoCiYeH                     }
140352da9a59SGnoCiYeH                     '#' => {
140452da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::EShash;
140552da9a59SGnoCiYeH                     }
140652da9a59SGnoCiYeH                     'c' => {
140752da9a59SGnoCiYeH                         self.reset(true);
140852da9a59SGnoCiYeH                     }
140952da9a59SGnoCiYeH                     '>' => {
141052da9a59SGnoCiYeH                         todo!("clr_kbd todo");
141152da9a59SGnoCiYeH                     }
141252da9a59SGnoCiYeH                     '=' => {
141352da9a59SGnoCiYeH                         todo!("set_kbd todo");
141452da9a59SGnoCiYeH                     }
141552da9a59SGnoCiYeH                     _ => {}
141652da9a59SGnoCiYeH                 }
141752da9a59SGnoCiYeH             }
141852da9a59SGnoCiYeH             VirtualConsoleState::ESsquare => {
141952da9a59SGnoCiYeH                 for i in self.par.iter_mut() {
142052da9a59SGnoCiYeH                     *i = 0;
142152da9a59SGnoCiYeH                 }
142252da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESgetpars;
142352da9a59SGnoCiYeH                 self.npar = 0;
142452da9a59SGnoCiYeH                 let c = ch as u8 as char;
142552da9a59SGnoCiYeH                 if c == '[' {
142652da9a59SGnoCiYeH                     self.vc_state = VirtualConsoleState::ESfunckey;
142752da9a59SGnoCiYeH                     return;
142852da9a59SGnoCiYeH                 }
142952da9a59SGnoCiYeH 
143052da9a59SGnoCiYeH                 match c {
143152da9a59SGnoCiYeH                     '?' => {
1432b5b571e0SLoGin                         self.private = Vt102_OP::Pdec;
143352da9a59SGnoCiYeH                         return;
143452da9a59SGnoCiYeH                     }
143552da9a59SGnoCiYeH                     '>' => {
1436b5b571e0SLoGin                         self.private = Vt102_OP::Pgt;
143752da9a59SGnoCiYeH                         return;
143852da9a59SGnoCiYeH                     }
143952da9a59SGnoCiYeH                     '=' => {
1440b5b571e0SLoGin                         self.private = Vt102_OP::Peq;
144152da9a59SGnoCiYeH                         return;
144252da9a59SGnoCiYeH                     }
144352da9a59SGnoCiYeH                     '<' => {
1444b5b571e0SLoGin                         self.private = Vt102_OP::Plt;
144552da9a59SGnoCiYeH                         return;
144652da9a59SGnoCiYeH                     }
144752da9a59SGnoCiYeH                     _ => {}
144852da9a59SGnoCiYeH                 }
144952da9a59SGnoCiYeH 
1450b5b571e0SLoGin                 self.private = Vt102_OP::Pecma;
145152da9a59SGnoCiYeH                 self.do_getpars(c);
145252da9a59SGnoCiYeH             }
145352da9a59SGnoCiYeH             VirtualConsoleState::ESgetpars => {
145452da9a59SGnoCiYeH                 let c = ch as u8 as char;
145552da9a59SGnoCiYeH                 self.do_getpars(c);
145652da9a59SGnoCiYeH             }
145752da9a59SGnoCiYeH             VirtualConsoleState::ESfunckey => {
145852da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESnormal;
145952da9a59SGnoCiYeH                 return;
146052da9a59SGnoCiYeH             }
146152da9a59SGnoCiYeH             VirtualConsoleState::EShash => {
146252da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESnormal;
146352da9a59SGnoCiYeH                 if ch as u8 as char == '8' {
146452da9a59SGnoCiYeH                     self.erase_char = (self.erase_char & 0xff00) | 'E' as u16;
146552da9a59SGnoCiYeH                     self.csi_J(2);
146652da9a59SGnoCiYeH                     self.erase_char = (self.erase_char & 0xff00) | ' ' as u16;
146752da9a59SGnoCiYeH                     self.do_update_region(0, self.screen_buf.len());
146852da9a59SGnoCiYeH                 }
146952da9a59SGnoCiYeH                 return;
147052da9a59SGnoCiYeH             }
147152da9a59SGnoCiYeH             VirtualConsoleState::ESsetG0 => {
147252da9a59SGnoCiYeH                 todo!("SetGx todo");
147352da9a59SGnoCiYeH             }
147452da9a59SGnoCiYeH             VirtualConsoleState::ESsetG1 => {
147552da9a59SGnoCiYeH                 todo!("SetGx todo");
147652da9a59SGnoCiYeH             }
147752da9a59SGnoCiYeH             VirtualConsoleState::ESpercent => {
147852da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESnormal;
147952da9a59SGnoCiYeH                 let c = ch as u8 as char;
148052da9a59SGnoCiYeH                 match c {
148152da9a59SGnoCiYeH                     '@' => {
148252da9a59SGnoCiYeH                         self.utf = false;
148352da9a59SGnoCiYeH                         return;
148452da9a59SGnoCiYeH                     }
148552da9a59SGnoCiYeH                     'G' | '8' => {
148652da9a59SGnoCiYeH                         self.utf = true;
148752da9a59SGnoCiYeH                         return;
148852da9a59SGnoCiYeH                     }
148952da9a59SGnoCiYeH                     _ => {}
149052da9a59SGnoCiYeH                 }
149152da9a59SGnoCiYeH                 return;
149252da9a59SGnoCiYeH             }
149352da9a59SGnoCiYeH             VirtualConsoleState::EScsiignore => {
1494b5b571e0SLoGin                 if (20..=0x3f).contains(&ch) {
149552da9a59SGnoCiYeH                     return;
149652da9a59SGnoCiYeH                 }
149752da9a59SGnoCiYeH                 self.vc_state = VirtualConsoleState::ESnormal;
149852da9a59SGnoCiYeH                 return;
149952da9a59SGnoCiYeH             }
150052da9a59SGnoCiYeH             VirtualConsoleState::ESnonstd => {
150152da9a59SGnoCiYeH                 let c = ch as u8 as char;
150252da9a59SGnoCiYeH                 if c == 'P' {
150352da9a59SGnoCiYeH                     for i in self.par.iter_mut() {
150452da9a59SGnoCiYeH                         *i = 0;
150552da9a59SGnoCiYeH                     }
150652da9a59SGnoCiYeH                     self.npar = 0;
150752da9a59SGnoCiYeH                     self.vc_state = VirtualConsoleState::ESpalette;
150852da9a59SGnoCiYeH                     return;
150952da9a59SGnoCiYeH                 } else if c == 'R' {
151052da9a59SGnoCiYeH                     self.reset_palette();
151152da9a59SGnoCiYeH                     self.vc_state = VirtualConsoleState::ESnormal;
1512b5b571e0SLoGin                 } else if c.is_ascii_digit() {
151352da9a59SGnoCiYeH                     self.vc_state = VirtualConsoleState::ESosc;
151452da9a59SGnoCiYeH                 } else {
151552da9a59SGnoCiYeH                     self.vc_state = VirtualConsoleState::ESnormal;
151652da9a59SGnoCiYeH                 }
151752da9a59SGnoCiYeH             }
151852da9a59SGnoCiYeH             VirtualConsoleState::ESpalette => {
151952da9a59SGnoCiYeH                 let c = ch as u8 as char;
1520b5b571e0SLoGin                 if c.is_ascii_hexdigit() {
152152da9a59SGnoCiYeH                     self.npar += 1;
152252da9a59SGnoCiYeH                     self.par[self.npar as usize] = c.to_digit(16).unwrap();
152352da9a59SGnoCiYeH 
152452da9a59SGnoCiYeH                     if self.npar == 7 {
152552da9a59SGnoCiYeH                         let mut i = self.par[0] as usize;
152652da9a59SGnoCiYeH                         let mut j = 0;
152752da9a59SGnoCiYeH                         self.palette[i].red = self.par[j] as u16;
152852da9a59SGnoCiYeH                         j += 1;
152952da9a59SGnoCiYeH                         self.palette[i].green = self.par[j] as u16;
153052da9a59SGnoCiYeH                         j += 1;
153152da9a59SGnoCiYeH                         self.palette[i].blue = self.par[j] as u16;
153252da9a59SGnoCiYeH                         j += 1;
153352da9a59SGnoCiYeH                         i += 1;
153452da9a59SGnoCiYeH                         self.palette[i].red = self.par[j] as u16;
153552da9a59SGnoCiYeH                         j += 1;
153652da9a59SGnoCiYeH                         self.palette[i].green = self.par[j] as u16;
153752da9a59SGnoCiYeH                         j += 1;
153852da9a59SGnoCiYeH                         self.palette[i].blue = self.par[j] as u16;
153952da9a59SGnoCiYeH                         self.set_palette();
154052da9a59SGnoCiYeH                         self.vc_state = VirtualConsoleState::ESnormal;
154152da9a59SGnoCiYeH                     }
154252da9a59SGnoCiYeH                 }
154352da9a59SGnoCiYeH             }
154452da9a59SGnoCiYeH             VirtualConsoleState::ESosc => {}
154552da9a59SGnoCiYeH             VirtualConsoleState::ESapc => {}
154652da9a59SGnoCiYeH             VirtualConsoleState::ESpm => {}
154752da9a59SGnoCiYeH             VirtualConsoleState::ESdcs => {}
154852da9a59SGnoCiYeH             VirtualConsoleState::ESnormal => {}
154952da9a59SGnoCiYeH         }
155052da9a59SGnoCiYeH     }
155152da9a59SGnoCiYeH 
155252bcb59eSGnoCiYeH     #[inline(never)]
155352da9a59SGnoCiYeH     pub(super) fn console_write_normal(
155452da9a59SGnoCiYeH         &mut self,
155552da9a59SGnoCiYeH         mut tc: u32,
155652da9a59SGnoCiYeH         c: u32,
155752da9a59SGnoCiYeH         draw: &mut DrawRegion,
155852da9a59SGnoCiYeH     ) -> bool {
155952da9a59SGnoCiYeH         let mut attr = self.attr;
156052da9a59SGnoCiYeH         let himask = self.hi_font_mask;
156152da9a59SGnoCiYeH         let charmask = if himask == 0 { 0xff } else { 0x1ff };
156252da9a59SGnoCiYeH         let mut width = 1;
156352da9a59SGnoCiYeH         // 表示需不需要反转
156452da9a59SGnoCiYeH         let mut invert = false;
1565b5b571e0SLoGin         if self.utf && !self.display_ctrl && FontDesc::is_double_width(c) {
156652da9a59SGnoCiYeH             width = 2;
156752da9a59SGnoCiYeH         }
156852da9a59SGnoCiYeH 
156952da9a59SGnoCiYeH         let tmp = self.unicode_to_index(tc);
157052da9a59SGnoCiYeH         if tmp & (!charmask as i32) != 0 {
157152da9a59SGnoCiYeH             if tmp == -1 || tmp == -2 {
157252da9a59SGnoCiYeH                 return false;
157352da9a59SGnoCiYeH             }
157452da9a59SGnoCiYeH 
157552da9a59SGnoCiYeH             // 未找到
157652da9a59SGnoCiYeH             if (!self.utf || self.display_ctrl || c < 128) && c & !charmask == 0 {
157752da9a59SGnoCiYeH                 tc = c;
157852da9a59SGnoCiYeH             } else {
157952da9a59SGnoCiYeH                 let tmp = self.unicode_to_index(0xfffd);
158052da9a59SGnoCiYeH                 if tmp < 0 {
158152da9a59SGnoCiYeH                     invert = true;
158252da9a59SGnoCiYeH                     let tmp = self.unicode_to_index('?' as u32);
158352da9a59SGnoCiYeH                     if tmp < 0 {
158452da9a59SGnoCiYeH                         tc = '?' as u32;
158552da9a59SGnoCiYeH                     } else {
158652da9a59SGnoCiYeH                         tc = tmp as u32;
158752da9a59SGnoCiYeH                     }
158852da9a59SGnoCiYeH 
158952da9a59SGnoCiYeH                     attr = self.invert_attr();
159052da9a59SGnoCiYeH                     self.flush(draw);
159152da9a59SGnoCiYeH                 }
159252da9a59SGnoCiYeH             }
159352da9a59SGnoCiYeH         }
159452da9a59SGnoCiYeH 
159552da9a59SGnoCiYeH         loop {
159652da9a59SGnoCiYeH             if self.need_wrap || self.insert_mode {
159752da9a59SGnoCiYeH                 self.flush(draw);
159852da9a59SGnoCiYeH             }
159952da9a59SGnoCiYeH             if self.need_wrap {
160052da9a59SGnoCiYeH                 self.carriage_return();
160152da9a59SGnoCiYeH                 self.line_feed();
160252da9a59SGnoCiYeH             }
160352da9a59SGnoCiYeH 
160452da9a59SGnoCiYeH             if self.insert_mode {
160552da9a59SGnoCiYeH                 self.insert_char(1);
160652da9a59SGnoCiYeH             }
160752da9a59SGnoCiYeH 
160852da9a59SGnoCiYeH             // TODO: 处理unicode screen buf
160952da9a59SGnoCiYeH 
161052da9a59SGnoCiYeH             if himask != 0 {
1611b5b571e0SLoGin                 tc = (if tc & 0x100 != 0 { himask as u32 } else { 0 }) | (tc & 0xff);
161252da9a59SGnoCiYeH             }
161352da9a59SGnoCiYeH 
161452da9a59SGnoCiYeH             tc |= ((attr as u32) << 8) & (!himask as u32);
161552da9a59SGnoCiYeH 
161652da9a59SGnoCiYeH             // kwarn!(
161752da9a59SGnoCiYeH             //     "ch {} pos {} x {} y {} cols {}",
161852da9a59SGnoCiYeH             //     c as u8 as char,
161952da9a59SGnoCiYeH             //     self.pos,
162052da9a59SGnoCiYeH             //     self.state.x,
162152da9a59SGnoCiYeH             //     self.state.y,
162252da9a59SGnoCiYeH             //     self.cols,
162352da9a59SGnoCiYeH             // );
162452da9a59SGnoCiYeH             self.screen_buf[self.pos] = tc as u16;
162552da9a59SGnoCiYeH 
162652da9a59SGnoCiYeH             if draw.x.is_none() {
162752da9a59SGnoCiYeH                 // 设置draw参数
162852da9a59SGnoCiYeH                 draw.x = Some(self.state.x as u32);
162952da9a59SGnoCiYeH                 draw.offset = self.pos;
163052da9a59SGnoCiYeH             }
163152da9a59SGnoCiYeH 
163252da9a59SGnoCiYeH             if self.state.x == self.cols - 1 {
163352da9a59SGnoCiYeH                 // 需要换行?
163452da9a59SGnoCiYeH                 self.need_wrap = self.autowrap;
163552da9a59SGnoCiYeH                 draw.size += 1;
163652da9a59SGnoCiYeH             } else {
163752da9a59SGnoCiYeH                 self.state.x += 1;
163852da9a59SGnoCiYeH                 self.pos += 1;
163952da9a59SGnoCiYeH                 draw.size += 1;
164052da9a59SGnoCiYeH             }
164152da9a59SGnoCiYeH 
164252da9a59SGnoCiYeH             width -= 1;
164352da9a59SGnoCiYeH             if width == 0 {
164452da9a59SGnoCiYeH                 break;
164552da9a59SGnoCiYeH             }
164652da9a59SGnoCiYeH             let tmp = self.unicode_to_index(' ' as u32);
164752da9a59SGnoCiYeH             tc = if tmp < 0 { ' ' as u32 } else { tmp as u32 };
164852da9a59SGnoCiYeH         }
164952da9a59SGnoCiYeH 
165052da9a59SGnoCiYeH         if invert {
165152da9a59SGnoCiYeH             self.flush(draw);
165252da9a59SGnoCiYeH         }
165352da9a59SGnoCiYeH 
165452da9a59SGnoCiYeH         true
165552da9a59SGnoCiYeH     }
165652da9a59SGnoCiYeH 
165752da9a59SGnoCiYeH     /// ## 当前vc插入nr个字符
165852da9a59SGnoCiYeH     fn insert_char(&mut self, nr: usize) {
165952da9a59SGnoCiYeH         // TODO: 管理unicode屏幕信息
166052da9a59SGnoCiYeH 
166152da9a59SGnoCiYeH         let pos = self.pos;
166252da9a59SGnoCiYeH         // 把当前位置以后得字符向后移动nr*2位
166352da9a59SGnoCiYeH         self.screen_buf[pos..].rotate_right(nr * 2);
166452da9a59SGnoCiYeH 
166552da9a59SGnoCiYeH         // 把空出来的位置用erase_char填充
166652da9a59SGnoCiYeH         for c in &mut self.screen_buf[pos..(pos + nr * 2)] {
166752da9a59SGnoCiYeH             *c = self.erase_char
166852da9a59SGnoCiYeH         }
166952da9a59SGnoCiYeH 
167052da9a59SGnoCiYeH         self.need_wrap = false;
167152da9a59SGnoCiYeH 
167252da9a59SGnoCiYeH         // 更新本行后面部分
167352da9a59SGnoCiYeH         self.do_update_region(self.pos, self.cols - self.state.x);
167452da9a59SGnoCiYeH     }
167552da9a59SGnoCiYeH 
167652da9a59SGnoCiYeH     /// ## 更新虚拟控制台指定区域的显示
167752da9a59SGnoCiYeH     fn do_update_region(&self, mut start: usize, mut count: usize) {
167852da9a59SGnoCiYeH         let ret = self.driver_funcs().con_getxy(self, start);
1679b5b571e0SLoGin         let (mut x, mut y) = if let Ok((_, tmp_x, tmp_y)) = ret {
168052bcb59eSGnoCiYeH             // start = tmp_start;
168152da9a59SGnoCiYeH             (tmp_x, tmp_y)
1682b5b571e0SLoGin         } else {
1683b5b571e0SLoGin             (start % self.cols, start / self.cols)
168452da9a59SGnoCiYeH         };
168552da9a59SGnoCiYeH 
168652da9a59SGnoCiYeH         loop {
168752da9a59SGnoCiYeH             // 记录当前字符的属性
168852da9a59SGnoCiYeH             let mut attr = self.screen_buf[start] & 0xff00;
168952da9a59SGnoCiYeH             let mut startx = x;
169052da9a59SGnoCiYeH             let mut size = 0;
169152da9a59SGnoCiYeH 
169252da9a59SGnoCiYeH             while count != 0 && x < self.cols {
169352da9a59SGnoCiYeH                 // 检查属性是否变化,如果属性变了,则将前一个字符先输出
1694b5b571e0SLoGin                 if attr != (self.screen_buf[start] & 0xff00) && size > 0 {
169552da9a59SGnoCiYeH                     let _ = self.driver_funcs().con_putcs(
169652da9a59SGnoCiYeH                         self,
169752da9a59SGnoCiYeH                         &self.screen_buf[start..],
169852da9a59SGnoCiYeH                         size,
169952da9a59SGnoCiYeH                         y as u32,
170052da9a59SGnoCiYeH                         startx as u32,
170152da9a59SGnoCiYeH                     );
170252da9a59SGnoCiYeH                     startx = x;
170352da9a59SGnoCiYeH                     start += size;
170452da9a59SGnoCiYeH                     size = 0;
170552da9a59SGnoCiYeH                     attr = self.screen_buf[start] & 0xff00;
170652da9a59SGnoCiYeH                 }
170752da9a59SGnoCiYeH                 size += 1;
170852da9a59SGnoCiYeH                 x += 1;
170952da9a59SGnoCiYeH                 count -= 1;
171052da9a59SGnoCiYeH             }
171152da9a59SGnoCiYeH 
171252da9a59SGnoCiYeH             if size > 0 {
171352da9a59SGnoCiYeH                 let _ = self.driver_funcs().con_putcs(
171452da9a59SGnoCiYeH                     self,
171552da9a59SGnoCiYeH                     &self.screen_buf[start..],
171652da9a59SGnoCiYeH                     size,
171752da9a59SGnoCiYeH                     y as u32,
171852da9a59SGnoCiYeH                     startx as u32,
171952da9a59SGnoCiYeH                 );
172052da9a59SGnoCiYeH             }
172152da9a59SGnoCiYeH             if count == 0 {
172252da9a59SGnoCiYeH                 break;
172352da9a59SGnoCiYeH             }
172452da9a59SGnoCiYeH 
172552da9a59SGnoCiYeH             // 一行
172652da9a59SGnoCiYeH             x = 0;
172752da9a59SGnoCiYeH             y += 1;
172852da9a59SGnoCiYeH 
172952da9a59SGnoCiYeH             let ret = self.driver_funcs().con_getxy(self, start);
1730b5b571e0SLoGin             if let Ok(ret) = ret {
1731b5b571e0SLoGin                 start = ret.0;
173252bcb59eSGnoCiYeH             } else {
173352bcb59eSGnoCiYeH                 return;
173452da9a59SGnoCiYeH             }
173552da9a59SGnoCiYeH         }
173652da9a59SGnoCiYeH     }
173752da9a59SGnoCiYeH 
173852da9a59SGnoCiYeH     const UNI_DIRECT_MAKS: u32 = 0x01ff;
173952da9a59SGnoCiYeH     const UNI_DIRECT_BASE: u32 = 0xf000;
174052da9a59SGnoCiYeH     /// ## unicode字符转对应的坐标,暂时这样写,还没有适配unicode
174152da9a59SGnoCiYeH     /// 这里是糊代码的,后面重写
174252da9a59SGnoCiYeH     fn unicode_to_index(&self, ch: u32) -> i32 {
174352da9a59SGnoCiYeH         if ch > 0xfff {
174452da9a59SGnoCiYeH             // 未找到
174552da9a59SGnoCiYeH             return -4;
174652da9a59SGnoCiYeH         } else if ch < 0x20 {
174752da9a59SGnoCiYeH             // 不可打印
174852da9a59SGnoCiYeH             return -1;
1749b5b571e0SLoGin         } else if ch == 0xfeff || (0x200b..=0x200f).contains(&ch) {
175052da9a59SGnoCiYeH             // 零长空格
175152da9a59SGnoCiYeH             return -2;
175252da9a59SGnoCiYeH         } else if (ch & !Self::UNI_DIRECT_MAKS) == Self::UNI_DIRECT_BASE {
175352da9a59SGnoCiYeH             return (ch & Self::UNI_DIRECT_MAKS) as i32;
175452da9a59SGnoCiYeH         }
175552da9a59SGnoCiYeH 
175652da9a59SGnoCiYeH         // TODO: 暂时这样写,表示不支持
175752da9a59SGnoCiYeH         return -3;
175852da9a59SGnoCiYeH     }
175952da9a59SGnoCiYeH 
176052da9a59SGnoCiYeH     fn invert_attr(&self) -> u8 {
176152da9a59SGnoCiYeH         if !self.color_mode {
176252da9a59SGnoCiYeH             return self.attr ^ 0x08;
176352da9a59SGnoCiYeH         }
176452da9a59SGnoCiYeH 
176552da9a59SGnoCiYeH         if self.hi_font_mask == 0x100 {
176652da9a59SGnoCiYeH             return (self.attr & 0x11) | ((self.attr & 0xe0) >> 4) | ((self.attr & 0x0e) << 4);
176752da9a59SGnoCiYeH         }
176852da9a59SGnoCiYeH 
176952da9a59SGnoCiYeH         return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4);
177052da9a59SGnoCiYeH     }
177152da9a59SGnoCiYeH 
177252da9a59SGnoCiYeH     pub(super) fn flush(&self, draw: &mut DrawRegion) {
177352da9a59SGnoCiYeH         if draw.x.is_none() {
177452da9a59SGnoCiYeH             return;
177552da9a59SGnoCiYeH         }
177652da9a59SGnoCiYeH 
177752da9a59SGnoCiYeH         let _ = self.driver_funcs().con_putcs(
177852da9a59SGnoCiYeH             self,
177952da9a59SGnoCiYeH             &self.screen_buf[draw.offset..draw.offset + draw.size],
178052da9a59SGnoCiYeH             draw.size,
178152da9a59SGnoCiYeH             self.state.y as u32,
1782b5b571e0SLoGin             draw.x.unwrap(),
178352da9a59SGnoCiYeH         );
178452da9a59SGnoCiYeH 
178552da9a59SGnoCiYeH         draw.x = None;
178652da9a59SGnoCiYeH         draw.size = 0;
178752da9a59SGnoCiYeH     }
178852da9a59SGnoCiYeH 
178952da9a59SGnoCiYeH     fn build_attr(
179052da9a59SGnoCiYeH         &self,
179152da9a59SGnoCiYeH         color: u8,
179252da9a59SGnoCiYeH         intensity: VirtualConsoleIntensity,
179352da9a59SGnoCiYeH         blink: bool,
179452da9a59SGnoCiYeH         underline: bool,
179552da9a59SGnoCiYeH         reverse: bool,
179652da9a59SGnoCiYeH         italic: bool,
179752da9a59SGnoCiYeH     ) -> u8 {
179852da9a59SGnoCiYeH         let ret = self
179952da9a59SGnoCiYeH             .driver_funcs()
180052da9a59SGnoCiYeH             .con_build_attr(self, color, intensity, blink, underline, reverse, italic);
180152da9a59SGnoCiYeH 
1802b5b571e0SLoGin         if let Ok(ret) = ret {
1803b5b571e0SLoGin             return ret;
180452da9a59SGnoCiYeH         }
180552da9a59SGnoCiYeH 
180652da9a59SGnoCiYeH         let mut ret = color;
180752da9a59SGnoCiYeH 
180852da9a59SGnoCiYeH         if !self.color_mode {
180952da9a59SGnoCiYeH             return intensity as u8
181052da9a59SGnoCiYeH                 | (italic as u8) << 1
181152da9a59SGnoCiYeH                 | (underline as u8) << 2
181252da9a59SGnoCiYeH                 | (reverse as u8) << 3
181352da9a59SGnoCiYeH                 | (blink as u8) << 7;
181452da9a59SGnoCiYeH         }
181552da9a59SGnoCiYeH 
181652da9a59SGnoCiYeH         if italic {
181752da9a59SGnoCiYeH             ret = (ret & 0xf0) | self.italic_color as u8;
181852da9a59SGnoCiYeH         } else if underline {
181952da9a59SGnoCiYeH             ret = (ret & 0xf0) | self.underline_color as u8;
1820b5b571e0SLoGin         } else if intensity == VirtualConsoleIntensity::HalfBright {
182152da9a59SGnoCiYeH             ret = (ret & 0xf0) | self.half_color as u8;
182252da9a59SGnoCiYeH         }
182352da9a59SGnoCiYeH 
182452da9a59SGnoCiYeH         if reverse {
182552da9a59SGnoCiYeH             ret = (ret & 0x88) | (((ret >> 4) | (ret << 4)) & 0x77);
182652da9a59SGnoCiYeH         }
182752da9a59SGnoCiYeH 
182852da9a59SGnoCiYeH         if blink {
182952da9a59SGnoCiYeH             ret ^= 0x80;
183052da9a59SGnoCiYeH         }
183152da9a59SGnoCiYeH 
1832b5b571e0SLoGin         if intensity == VirtualConsoleIntensity::Bold {
183352da9a59SGnoCiYeH             ret ^= 0x08;
183452da9a59SGnoCiYeH         }
183552da9a59SGnoCiYeH 
183652da9a59SGnoCiYeH         if self.hi_font_mask == 0x100 {
183752da9a59SGnoCiYeH             ret <<= 1;
183852da9a59SGnoCiYeH         }
183952da9a59SGnoCiYeH 
184052da9a59SGnoCiYeH         ret
184152da9a59SGnoCiYeH     }
184252da9a59SGnoCiYeH 
184352da9a59SGnoCiYeH     pub(super) fn update_attr(&mut self) {
184452da9a59SGnoCiYeH         self.attr = self.build_attr(
184552da9a59SGnoCiYeH             self.state.color,
184652da9a59SGnoCiYeH             self.state.intensity,
184752da9a59SGnoCiYeH             self.state.blink,
184852da9a59SGnoCiYeH             self.state.underline,
184952da9a59SGnoCiYeH             self.state.reverse ^ self.screen_mode,
185052da9a59SGnoCiYeH             self.state.italic,
185152da9a59SGnoCiYeH         );
185252da9a59SGnoCiYeH 
185352da9a59SGnoCiYeH         self.erase_char = ' ' as u16
185452da9a59SGnoCiYeH             | ((self.build_attr(
185552da9a59SGnoCiYeH                 self.state.color,
1856b5b571e0SLoGin                 VirtualConsoleIntensity::Normal,
185752da9a59SGnoCiYeH                 self.state.blink,
185852da9a59SGnoCiYeH                 false,
185952da9a59SGnoCiYeH                 self.screen_mode,
186052da9a59SGnoCiYeH                 false,
186152da9a59SGnoCiYeH             ) as u16)
186252da9a59SGnoCiYeH                 << 8);
186352da9a59SGnoCiYeH     }
186452da9a59SGnoCiYeH 
186552da9a59SGnoCiYeH     fn default_attr(&mut self) {
1866b5b571e0SLoGin         self.state.intensity = VirtualConsoleIntensity::Normal;
186752da9a59SGnoCiYeH         self.state.italic = false;
186852da9a59SGnoCiYeH         self.state.underline = false;
186952da9a59SGnoCiYeH         self.state.reverse = false;
187052da9a59SGnoCiYeH         self.state.blink = false;
187152da9a59SGnoCiYeH         self.state.color = self.def_color;
187252da9a59SGnoCiYeH     }
187352da9a59SGnoCiYeH }
187452da9a59SGnoCiYeH 
187552da9a59SGnoCiYeH /// ## 虚拟控制台的状态信息
187652da9a59SGnoCiYeH #[derive(Debug, Default, Clone)]
187752da9a59SGnoCiYeH pub struct VirtualConsoleInfo {
187852da9a59SGnoCiYeH     // x,y表示光标坐标
187952da9a59SGnoCiYeH     pub x: usize,
188052da9a59SGnoCiYeH     pub y: usize,
188152da9a59SGnoCiYeH     pub color: u8,
188252da9a59SGnoCiYeH 
188352da9a59SGnoCiYeH     /// 表示字符的强度
188452da9a59SGnoCiYeH     intensity: VirtualConsoleIntensity,
188552da9a59SGnoCiYeH     /// 斜体
188652da9a59SGnoCiYeH     italic: bool,
188752da9a59SGnoCiYeH     /// 下划线
188852da9a59SGnoCiYeH     underline: bool,
188952da9a59SGnoCiYeH     /// 字符闪烁
189052da9a59SGnoCiYeH     blink: bool,
189152da9a59SGnoCiYeH     /// 前景与背景色反转
189252da9a59SGnoCiYeH     reverse: bool,
189352da9a59SGnoCiYeH }
189452da9a59SGnoCiYeH 
189552da9a59SGnoCiYeH impl VirtualConsoleInfo {
189652da9a59SGnoCiYeH     pub fn new(x: usize, y: usize) -> Self {
189752da9a59SGnoCiYeH         Self {
189852da9a59SGnoCiYeH             x,
189952da9a59SGnoCiYeH             y,
190052da9a59SGnoCiYeH             color: Default::default(),
190152da9a59SGnoCiYeH             intensity: Default::default(),
190252da9a59SGnoCiYeH             italic: Default::default(),
190352da9a59SGnoCiYeH             underline: Default::default(),
190452da9a59SGnoCiYeH             blink: Default::default(),
190552da9a59SGnoCiYeH             reverse: Default::default(),
190652da9a59SGnoCiYeH         }
190752da9a59SGnoCiYeH     }
190852da9a59SGnoCiYeH }
190952da9a59SGnoCiYeH 
191052da9a59SGnoCiYeH /// 字符强度
191152da9a59SGnoCiYeH #[derive(Debug, Clone, PartialEq, Copy)]
191252da9a59SGnoCiYeH pub enum VirtualConsoleIntensity {
191352da9a59SGnoCiYeH     /// 暗淡
1914b5b571e0SLoGin     HalfBright = 0,
191552da9a59SGnoCiYeH     /// 正常
1916b5b571e0SLoGin     Normal = 1,
191752da9a59SGnoCiYeH     /// 粗体
1918b5b571e0SLoGin     Bold = 2,
191952da9a59SGnoCiYeH }
192052da9a59SGnoCiYeH 
192152da9a59SGnoCiYeH impl Default for VirtualConsoleIntensity {
192252da9a59SGnoCiYeH     fn default() -> Self {
1923b5b571e0SLoGin         Self::Normal
192452da9a59SGnoCiYeH     }
192552da9a59SGnoCiYeH }
192652da9a59SGnoCiYeH 
192752da9a59SGnoCiYeH /// ## 虚拟控制台的状态
192852da9a59SGnoCiYeH ///
192952da9a59SGnoCiYeH /// 可以把VC的接收字符理解为一个状态机
193052da9a59SGnoCiYeH #[derive(Debug, PartialEq, Clone)]
193152da9a59SGnoCiYeH pub enum VirtualConsoleState {
193252da9a59SGnoCiYeH     /// 正常状态
193352da9a59SGnoCiYeH     ESnormal,
193452da9a59SGnoCiYeH     /// 收到了转义字符 \e,即"Escape"字符
193552da9a59SGnoCiYeH     ESesc,
193652da9a59SGnoCiYeH     /// 收到了 "[" 字符,通常是 ANSI 控制序列的开始
193752da9a59SGnoCiYeH     ESsquare,
193852da9a59SGnoCiYeH     /// 解析参数状态
193952da9a59SGnoCiYeH     ESgetpars,
194052da9a59SGnoCiYeH     /// 功能键状态
194152da9a59SGnoCiYeH     ESfunckey,
194252da9a59SGnoCiYeH     /// 收到了 "#" 字符
194352da9a59SGnoCiYeH     EShash,
194452da9a59SGnoCiYeH     /// 设置 G0 字符集状态
194552da9a59SGnoCiYeH     ESsetG0,
194652da9a59SGnoCiYeH     /// 设置 G1 字符集状态
194752da9a59SGnoCiYeH     ESsetG1,
194852da9a59SGnoCiYeH     /// 收到了 "%" 字符
194952da9a59SGnoCiYeH     ESpercent,
195052da9a59SGnoCiYeH     /// 忽略 ANSI 控制序列状态
195152da9a59SGnoCiYeH     EScsiignore,
195252da9a59SGnoCiYeH     /// 非标准字符状态
195352da9a59SGnoCiYeH     ESnonstd,
195452da9a59SGnoCiYeH     /// 调色板状态
195552da9a59SGnoCiYeH     ESpalette,
195652da9a59SGnoCiYeH     /// Operating System Command (OSC) 状态
195752da9a59SGnoCiYeH     ESosc,
195852da9a59SGnoCiYeH     ///  Application Program Command (APC) 状态
195952da9a59SGnoCiYeH     ESapc,
196052da9a59SGnoCiYeH     /// Privacy Message (PM) 状态
196152da9a59SGnoCiYeH     ESpm,
196252da9a59SGnoCiYeH     /// Device Control String (DCS) 状态
196352da9a59SGnoCiYeH     ESdcs,
196452da9a59SGnoCiYeH }
196552da9a59SGnoCiYeH 
196652da9a59SGnoCiYeH impl VirtualConsoleState {
196752da9a59SGnoCiYeH     pub fn is_ansi_control_string(&self) -> bool {
196852da9a59SGnoCiYeH         if *self == Self::ESosc
196952da9a59SGnoCiYeH             || *self == Self::ESapc
197052da9a59SGnoCiYeH             || *self == Self::ESpm
197152da9a59SGnoCiYeH             || *self == Self::ESdcs
197252da9a59SGnoCiYeH         {
197352da9a59SGnoCiYeH             return true;
197452da9a59SGnoCiYeH         }
197552da9a59SGnoCiYeH 
197652da9a59SGnoCiYeH         false
197752da9a59SGnoCiYeH     }
197852da9a59SGnoCiYeH }
197952da9a59SGnoCiYeH 
198052da9a59SGnoCiYeH #[derive(Debug, Clone, PartialEq, PartialOrd)]
198152da9a59SGnoCiYeH #[allow(non_camel_case_types)]
198252da9a59SGnoCiYeH pub enum Vt102_OP {
1983b5b571e0SLoGin     Pecma,
1984b5b571e0SLoGin     Pdec,
1985b5b571e0SLoGin     Peq,
1986b5b571e0SLoGin     Pgt,
1987b5b571e0SLoGin     Plt,
198852da9a59SGnoCiYeH }
198952da9a59SGnoCiYeH 
199052da9a59SGnoCiYeH bitflags! {
199152da9a59SGnoCiYeH     #[derive(Default)]
199252da9a59SGnoCiYeH     pub struct VcCursor: u32 {
199352da9a59SGnoCiYeH         /// 默认
199452da9a59SGnoCiYeH         const CUR_DEF			=       0;
199552da9a59SGnoCiYeH         /// 无光标
199652da9a59SGnoCiYeH         const CUR_NONE			=       1;
199752da9a59SGnoCiYeH         /// 下划线形式
199852da9a59SGnoCiYeH         const CUR_UNDERLINE		=	    2;
199952da9a59SGnoCiYeH         /// 光标占据底部的三分之一
200052da9a59SGnoCiYeH         const CUR_LOWER_THIRD	=	    3;
200152da9a59SGnoCiYeH         /// 光标占据底部的一半
200252da9a59SGnoCiYeH         const CUR_LOWER_HALF	=       4;
200352da9a59SGnoCiYeH         ///  光标占据底部的三分之二
200452da9a59SGnoCiYeH         const CUR_TWO_THIRDS	=       5;
200552da9a59SGnoCiYeH         /// 光标为块状(方块)形式
200652da9a59SGnoCiYeH         const CUR_BLOCK			=       6;
200752da9a59SGnoCiYeH         /// 光标属性,用于指示软件光标
200852da9a59SGnoCiYeH         const CUR_SW			=	0x000010;
200952da9a59SGnoCiYeH         /// 光标属性,用于指示光标是否始终在背景上显示
201052da9a59SGnoCiYeH         const CUR_ALWAYS_BG		=	0x000020;
201152da9a59SGnoCiYeH         /// 光标属性,用于指示前景和背景是否反转
201252da9a59SGnoCiYeH         const CUR_INVERT_FG_BG	=	0x000040;
201352da9a59SGnoCiYeH         /// 光标前景色属性,用于指定光标的前景色
201452da9a59SGnoCiYeH         const CUR_FG			=	0x000700;
201552da9a59SGnoCiYeH         /// 光标背景色属性,用于指定光标的背景色
201652da9a59SGnoCiYeH         const CUR_BG			=	0x007000;
201752da9a59SGnoCiYeH     }
201852da9a59SGnoCiYeH }
201952da9a59SGnoCiYeH 
202052da9a59SGnoCiYeH impl VcCursor {
202152da9a59SGnoCiYeH     pub fn make_cursor(size: u32, change: u32, set: u32) -> Self {
202252da9a59SGnoCiYeH         unsafe { Self::from_bits_unchecked(size | (change << 8) | (set << 16)) }
202352da9a59SGnoCiYeH     }
202452da9a59SGnoCiYeH 
202552da9a59SGnoCiYeH     pub fn cursor_size(&self) -> Self {
202652da9a59SGnoCiYeH         Self::from_bits_truncate(self.bits & 0x00000f)
202752da9a59SGnoCiYeH     }
202852da9a59SGnoCiYeH 
202952da9a59SGnoCiYeH     pub fn cursor_set(&self) -> u32 {
203052da9a59SGnoCiYeH         (self.bits & 0xff0000) >> 8
203152da9a59SGnoCiYeH     }
203252da9a59SGnoCiYeH 
203352da9a59SGnoCiYeH     pub fn cursor_change(&self) -> u32 {
203452da9a59SGnoCiYeH         self.bits & 0x00ff00
203552da9a59SGnoCiYeH     }
203652da9a59SGnoCiYeH }
203752da9a59SGnoCiYeH 
203852da9a59SGnoCiYeH #[derive(Debug, PartialEq)]
203952da9a59SGnoCiYeH #[allow(dead_code)]
204052da9a59SGnoCiYeH pub enum CursorOperation {
204152da9a59SGnoCiYeH     Draw,
204252da9a59SGnoCiYeH     Erase,
204352da9a59SGnoCiYeH     Move,
204452da9a59SGnoCiYeH }
204552da9a59SGnoCiYeH 
204652da9a59SGnoCiYeH #[derive(Debug, PartialEq, Clone, Copy)]
204752da9a59SGnoCiYeH pub enum ScrollDir {
204852da9a59SGnoCiYeH     Up,
204952da9a59SGnoCiYeH     Down,
205052da9a59SGnoCiYeH }
2051