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