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