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