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