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