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