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)] 147 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::Pecma, 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::Lat1), 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 208 pub(super) fn init(&mut self, rows: Option<usize>, cols: Option<usize>, clear: bool) { 209 if let Some(rows) = rows { 210 self.rows = rows; 211 } 212 if let Some(cols) = cols { 213 self.cols = cols; 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 229 pub fn should_update(&self) -> bool { 230 self.is_visible() && !CONSOLE_BLANKED.load(Ordering::SeqCst) 231 } 232 233 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 242 fn driver_funcs(&self) -> Arc<dyn ConsoleSwitch> { 243 self.driver_funcs.as_ref().unwrap().upgrade().unwrap() 244 } 245 246 pub(super) fn set_driver_funcs(&mut self, func: Weak<dyn ConsoleSwitch>) { 247 self.driver_funcs = Some(func); 248 } 249 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::Lat1); 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 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 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) 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 let Some(ret) = ret { 325 *c = ret; 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时,元组的第一个数据是无效数据(未转换完成) 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 414 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 替代字符。 427 fn sanitize_unicode(c: u32) -> u32 { 428 if (0xd800..=0xdfff).contains(&c) || 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下是不是需要显示的控制字符 444 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 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 /// ## 添加软光标 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) }); 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 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 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 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的光标移动到目标位置 560 fn gotoxy(&mut self, x: i32, y: i32) { 561 if x < 0 { 562 self.state.x = 0; 563 } else if x as usize >= self.cols { 564 self.state.x = self.cols - 1; 565 } else { 566 self.state.x = x as usize; 567 } 568 569 let max_y; 570 let min_y; 571 if self.origin_mode { 572 min_y = self.top; 573 max_y = self.bottom - 1; 574 } else { 575 min_y = 0; 576 max_y = self.rows - 1; 577 } 578 579 if y < min_y as i32 { 580 self.state.y = min_y; 581 } else if y >= max_y as i32 { 582 self.state.y = max_y; 583 } else { 584 self.state.y = y as usize; 585 } 586 587 self.pos = self.state.y * self.cols + self.state.x; 588 self.need_wrap = false; 589 } 590 591 fn scroll(&mut self, dir: ScrollDir, mut nr: usize) { 592 // todo: uniscr_srceen 593 if self.top + nr >= self.bottom { 594 // 滚动超过一页,则按一页计算 595 nr = self.bottom - self.top - 1; 596 } 597 598 if nr < 1 { 599 return; 600 } 601 602 if self.is_visible() 603 && self 604 .driver_funcs() 605 .con_scroll(self, self.top, self.bottom, dir, nr) 606 { 607 // 如果成功 608 return; 609 } 610 611 // 调整screen_buf 612 let count = nr * self.cols; 613 if dir == ScrollDir::Up { 614 for i in self.screen_buf[0..count].iter_mut() { 615 *i = self.erase_char; 616 } 617 self.screen_buf.rotate_left(count); 618 } else if dir == ScrollDir::Down { 619 todo!(); 620 } 621 } 622 623 /// ## 退格 624 fn backspace(&mut self) { 625 if self.state.x > 0 { 626 self.pos -= 1; 627 self.state.x -= 1; 628 self.need_wrap = false; 629 630 // TODO: notify 631 } 632 } 633 634 /// ## 换行 635 fn line_feed(&mut self) { 636 if self.state.y + 1 == self.bottom { 637 self.scroll(ScrollDir::Up, 1); 638 } else if self.state.y < self.rows - 1 { 639 self.state.y += 1; 640 self.pos += self.cols; 641 } 642 643 self.need_wrap = false; 644 // TODO: Notify write 645 } 646 647 /// ## 回车 648 fn carriage_return(&mut self) { 649 // 写入位置回退到该行最前 650 self.pos -= self.state.x; 651 self.need_wrap = false; 652 self.state.x = 0; 653 } 654 655 /// ## Del 656 fn delete(&mut self) { 657 // ignore 658 } 659 660 /// ## 向上滚动虚拟终端的内容,或者将光标上移一行 661 fn reverse_index(&mut self) { 662 if self.state.y == self.top { 663 self.scroll(ScrollDir::Down, 1); 664 } else if self.state.y > 0 { 665 self.state.y -= 1; 666 self.pos -= self.cols; 667 } 668 self.need_wrap = false; 669 } 670 671 /// https://code.dragonos.org.cn/xref/linux-6.1.9/drivers/tty/vt/vt.c#restore_cur 672 fn restore_cursor(&mut self) { 673 self.saved_state = self.state.clone(); 674 675 self.gotoxy(self.state.x as i32, self.state.y as i32); 676 677 // TODO Gx_charset 678 679 self.update_attr(); 680 self.need_wrap = false; 681 todo!() 682 } 683 684 /// ## 设置当前vt的各项属性 685 fn set_mode(&mut self, on_off: bool) { 686 for i in 0..self.npar as usize { 687 if self.private == Vt102_OP::Pdec { 688 match self.par[i] { 689 1 => { 690 todo!("kbd todo"); 691 } 692 3 => { 693 todo!("reisze todo"); 694 } 695 5 => { 696 todo!("invert_screen todo"); 697 } 698 6 => { 699 self.origin_mode = on_off; 700 if on_off { 701 self.gotoxy(0, self.top as i32); 702 } else { 703 self.gotoxy(0, 0); 704 } 705 } 706 7 => { 707 self.autowrap = on_off; 708 } 709 8 => { 710 todo!("kbd todo"); 711 } 712 9 => { 713 todo!("report mouse todo"); 714 } 715 25 => { 716 self.cursor_visible = on_off; 717 } 718 1000 => { 719 todo!("report mouse todo"); 720 } 721 _ => {} 722 } 723 } else { 724 match self.par[i] { 725 3 => { 726 self.display_ctrl = on_off; 727 } 728 4 => { 729 self.insert_mode = on_off; 730 } 731 20 => { 732 todo!("kbd todo"); 733 } 734 _ => {} 735 } 736 } 737 } 738 } 739 740 #[inline(never)] 741 fn do_getpars(&mut self, c: char) { 742 if c == ';' && self.npar < (NPAR - 1) as u32 { 743 self.npar += 1; 744 return; 745 } 746 747 if c.is_ascii_digit() { 748 self.par[self.npar as usize] *= 10; 749 self.par[self.npar as usize] += (c as u8 - b'0') as u32; 750 return; 751 } 752 753 if c as u8 >= 0x20 && c as u8 <= 0x3f { 754 self.vc_state = VirtualConsoleState::EScsiignore; 755 return; 756 } 757 758 self.vc_state = VirtualConsoleState::ESnormal; 759 760 match c { 761 'h' => { 762 if self.private <= Vt102_OP::Pdec { 763 self.set_mode(true); 764 } 765 return; 766 } 767 'l' => { 768 if self.private <= Vt102_OP::Pdec { 769 self.set_mode(false); 770 } 771 return; 772 } 773 'c' => { 774 if self.private == Vt102_OP::Pdec { 775 if self.par[0] != 0 { 776 self.cursor_type = 777 VcCursor::make_cursor(self.par[0], self.par[1], self.par[2]) 778 } else { 779 self.cursor_type = VcCursor::CUR_UNDERLINE; 780 } 781 return; 782 } 783 } 784 'm' => { 785 if self.private == Vt102_OP::Pdec { 786 if self.par[0] != 0 { 787 self.complement_mask = (self.par[0] << 8 | self.par[1]) as u16; 788 } else { 789 self.complement_mask = self.s_complement_mask; 790 } 791 return; 792 } 793 } 794 'n' => { 795 if self.private == Vt102_OP::Pecma { 796 if self.par[0] == 5 { 797 send_to_default_serial8250_port("tty status report todo".as_bytes()); 798 panic!(); 799 } else if self.par[0] == 6 { 800 send_to_default_serial8250_port("tty cursor report todo".as_bytes()); 801 panic!(); 802 } 803 } 804 return; 805 } 806 _ => {} 807 } 808 809 if self.private != Vt102_OP::Pecma { 810 self.private = Vt102_OP::Pecma; 811 return; 812 } 813 814 match c { 815 'G' | '`' => { 816 if self.par[0] != 0 { 817 self.par[0] -= 1; 818 } 819 self.gotoxy(self.par[0] as i32, self.state.y as i32); 820 return; 821 } 822 'A' => { 823 if self.par[0] == 0 { 824 self.par[0] += 1; 825 } 826 self.gotoxy( 827 self.state.x as i32, 828 (self.state.y - self.par[0] as usize) as i32, 829 ); 830 return; 831 } 832 'B' | 'e' => { 833 if self.par[0] == 0 { 834 self.par[0] += 1; 835 } 836 self.gotoxy( 837 self.state.x as i32, 838 (self.state.y + self.par[0] as usize) as i32, 839 ); 840 return; 841 } 842 'C' | 'a' => { 843 if self.par[0] == 0 { 844 self.par[0] += 1; 845 } 846 self.gotoxy( 847 (self.state.x + self.par[0] as usize) as i32, 848 self.state.y as i32, 849 ); 850 return; 851 } 852 'D' => { 853 if self.par[0] == 0 { 854 self.par[0] += 1; 855 } 856 self.gotoxy( 857 self.state.x as i32 - self.par[0] as i32, 858 self.state.y as i32, 859 ); 860 return; 861 } 862 'E' => { 863 if self.par[0] == 0 { 864 self.par[0] += 1; 865 } 866 self.gotoxy(0, (self.state.y + self.par[0] as usize) as i32); 867 return; 868 } 869 'F' => { 870 if self.par[0] == 0 { 871 self.par[0] += 1; 872 } 873 self.gotoxy(0, self.state.y as i32 - self.par[0] as i32); 874 return; 875 } 876 'd' => { 877 if self.par[0] != 0 { 878 self.par[0] -= 1; 879 } 880 self.gotoxay(self.state.x as i32, self.par[0] as i32); 881 return; 882 } 883 'H' | 'f' => { 884 // MOVETO 885 if self.par[0] != 0 { 886 self.par[0] -= 1; 887 } 888 if self.par[1] != 0 { 889 self.par[1] -= 1; 890 } 891 self.gotoxay(self.par[1] as i32, self.par[0] as i32); 892 return; 893 } 894 'J' => { 895 self.csi_J(self.par[0]); 896 return; 897 } 898 'K' => { 899 self.csi_K(self.par[0]); 900 return; 901 } 902 'L' => { 903 todo!("csi_L todo"); 904 } 905 'M' => { 906 todo!("csi_M todo"); 907 } 908 'P' => { 909 todo!("csi_P todo"); 910 } 911 912 // 非ANSI标准,为ANSI拓展 913 'S' => { 914 self.scroll(ScrollDir::Up, self.par[0] as usize); 915 return; 916 } 917 918 'T' => { 919 self.scroll(ScrollDir::Down, self.par[0] as usize); 920 return; 921 } 922 923 'c' => { 924 if self.par[0] == 0 { 925 kwarn!("respone ID todo"); 926 } 927 return; 928 } 929 'g' => { 930 if self.par[0] == 0 && self.state.x < 256 { 931 self.tab_stop.set(self.state.x, true); 932 } else if self.par[0] == 3 { 933 self.tab_stop.set_all(false); 934 } 935 return; 936 } 937 'm' => { 938 self.csi_m(); 939 return; 940 } 941 'q' => { 942 if self.par[0] < 4 { 943 todo!("vt set led state todo"); 944 } 945 return; 946 } 947 'r' => { 948 if self.par[0] == 0 { 949 self.par[0] += 1; 950 } 951 if self.par[1] == 0 { 952 self.par[1] = self.rows as u32; 953 } 954 if self.par[0] < self.par[1] && self.par[1] <= self.rows as u32 { 955 self.top = self.par[0] as usize - 1; 956 self.bottom = self.par[1] as usize; 957 self.gotoxay(0, 0); 958 } 959 return; 960 } 961 's' => { 962 self.saved_state = self.state.clone(); 963 return; 964 } 965 'u' => { 966 self.restore_cursor(); 967 return; 968 } 969 '@' => { 970 todo!("csi_at todo"); 971 } 972 ']' => { 973 todo!("set termial command todo"); 974 } 975 _ => {} 976 } 977 } 978 979 /// ## 处理Control Sequence Introducer(控制序列引导符) m字符 980 #[inline(never)] 981 fn csi_m(&mut self) { 982 let mut i = 0; 983 loop { 984 if i > self.npar as usize { 985 break; 986 } 987 match self.par[i] { 988 0 => { 989 // 关闭所有属性 990 self.default_attr(); 991 } 992 993 1 => { 994 // 设置粗体 995 self.state.intensity = VirtualConsoleIntensity::Bold; 996 } 997 998 2 => { 999 // 设置半亮度(半明显 1000 self.state.intensity = VirtualConsoleIntensity::HalfBright; 1001 } 1002 1003 3 => { 1004 // 斜体 1005 self.state.italic = true; 1006 } 1007 1008 4 | 21 => { 1009 // 下划线 1010 1011 // 21是设置双下划线,但是不支持,就单下划线 1012 self.state.underline = true; 1013 } 1014 1015 5 => { 1016 // 设置闪烁 1017 self.state.blink = true; 1018 } 1019 1020 7 => { 1021 // 设置反显(前景色与背景色对调) 1022 self.state.reverse = true; 1023 } 1024 1025 10 => { 1026 // 选择主要字体 1027 todo!() 1028 } 1029 1030 11 => { 1031 // 选择第一个替代字体 1032 todo!() 1033 } 1034 1035 12 => { 1036 // 选择第二个替代字体 1037 todo!() 1038 } 1039 1040 22 => { 1041 // 关闭粗体和半亮度,恢复正常亮度 1042 self.state.intensity = VirtualConsoleIntensity::Normal; 1043 } 1044 1045 23 => { 1046 // 关闭斜体 1047 self.state.italic = false; 1048 } 1049 1050 24 => { 1051 // 关闭下划线 1052 self.state.underline = false; 1053 } 1054 1055 25 => { 1056 // 关闭字符闪烁 1057 self.state.blink = false; 1058 } 1059 1060 27 => { 1061 // 关闭反显 1062 self.state.reverse = false; 1063 } 1064 1065 38 => { 1066 // 设置前景色 1067 let (idx, color) = self.t416_color(i); 1068 i = idx; 1069 if let Some(color) = color { 1070 let mut max = color.red.max(color.green); 1071 max = max.max(color.blue); 1072 1073 let mut hue = 0; 1074 if color.red > max / 2 { 1075 hue |= 4; 1076 } 1077 if color.green > max / 2 { 1078 hue |= 2; 1079 } 1080 if color.blue > max / 2 { 1081 hue |= 1; 1082 } 1083 1084 if hue == 7 && max <= 0x55 { 1085 hue = 0; 1086 self.state.intensity = VirtualConsoleIntensity::Bold; 1087 } else if max > 0xaa { 1088 self.state.intensity = VirtualConsoleIntensity::Bold; 1089 } else { 1090 self.state.intensity = VirtualConsoleIntensity::Normal; 1091 } 1092 1093 self.state.color = (self.state.color & 0xf0) | hue; 1094 } 1095 } 1096 1097 48 => { 1098 // 设置背景色 1099 let (idx, color) = self.t416_color(i); 1100 i = idx; 1101 if let Some(color) = color { 1102 self.state.color = (self.state.color & 0x0f) 1103 | ((color.red as u8 & 0x80) >> 1) 1104 | ((color.green as u8 & 0x80) >> 2) 1105 | ((color.blue as u8 & 0x80) >> 3); 1106 } 1107 } 1108 1109 39 => { 1110 // 恢复默认前景色 1111 self.state.color = (self.def_color & 0x0f) | (self.state.color & 0xf0); 1112 } 1113 1114 49 => { 1115 // 恢复默认背景色 1116 self.state.color = (self.def_color & 0xf0) | (self.state.color & 0x0f); 1117 } 1118 1119 _ => { 1120 if self.par[i] >= 90 && self.par[i] <= 107 { 1121 if self.par[i] < 100 { 1122 self.state.intensity = VirtualConsoleIntensity::Bold; 1123 } 1124 self.par[i] -= 60; 1125 } 1126 1127 if self.par[i] >= 30 && self.par[i] <= 37 { 1128 self.state.color = 1129 COLOR_TABLE[self.par[i] as usize - 30] | self.state.color & 0xf0; 1130 } else if self.par[i] >= 40 && self.par[i] <= 47 { 1131 self.state.color = 1132 (COLOR_TABLE[self.par[i] as usize - 40] << 4) | self.state.color & 0xf0; 1133 } 1134 } 1135 } 1136 1137 i += 1; 1138 } 1139 1140 self.update_attr(); 1141 } 1142 1143 /// ## 处理Control Sequence Introducer(控制序列引导符) J字符 1144 /// 该命令用于擦除终端显示区域的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作: 1145 /// - vpar 为 0 时,擦除从光标位置到显示区域末尾的内容; 1146 /// - vpar 为 1 时,擦除从显示区域起始位置到光标位置的内容; 1147 /// - vpar 为 2 或 3 时,分别表示擦除整个显示区域的内容,其中参数 3 还会清除回滚缓冲区的内容。 1148 #[allow(non_snake_case)] 1149 fn csi_J(&mut self, vpar: u32) { 1150 let count; 1151 let start; 1152 1153 match vpar { 1154 0 => { 1155 // 擦除从光标位置到显示区域末尾的内容 1156 count = self.screen_buf.len() - self.pos; 1157 start = self.pos; 1158 } 1159 1 => { 1160 // 擦除从显示区域起始位置到光标位置的内容 1161 count = self.pos; 1162 start = 0; 1163 } 1164 2 => { 1165 // 擦除整个显示区域的内容 1166 count = self.screen_buf.len(); 1167 start = 0; 1168 } 1169 3 => { 1170 // 表示擦除整个显示区域的内容,还会清除回滚缓冲区的内容 1171 // TODO:当前未实现回滚缓冲 1172 count = self.screen_buf.len(); 1173 start = 0; 1174 } 1175 _ => { 1176 return; 1177 } 1178 } 1179 1180 for i in self.screen_buf[start..(start + count)].iter_mut() { 1181 *i = self.erase_char; 1182 } 1183 1184 if self.should_update() { 1185 self.do_update_region(start, count) 1186 } 1187 1188 self.need_wrap = false; 1189 } 1190 1191 /// ## 处理Control Sequence Introducer(控制序列引导符) K字符 1192 /// 该命令用于擦除终端当前行的部分或全部内容。根据参数 vpar 的不同值,执行不同的擦除操作: 1193 /// - vpar 为 0 时,擦除从光标位置到该行末尾的内容 1194 /// - vpar 为 1 时,擦除从该行起始位置到光标位置的内容 1195 /// - vpar 为 2 时,擦除整个行。 1196 #[allow(non_snake_case)] 1197 fn csi_K(&mut self, vpar: u32) { 1198 let count; 1199 let start; 1200 1201 match vpar { 1202 0 => { 1203 // 擦除从光标位置到该行末尾的内容 1204 count = self.cols - self.state.x; 1205 start = self.pos; 1206 } 1207 1 => { 1208 // 擦除从该行起始位置到光标位置的内容 1209 count = self.state.x + 1; 1210 start = self.pos - self.state.x; 1211 } 1212 2 => { 1213 // 擦除整个行 1214 count = self.cols; 1215 start = self.pos - self.state.x; 1216 } 1217 _ => { 1218 return; 1219 } 1220 } 1221 1222 let max_idx = self.screen_buf.len(); 1223 for i in self.screen_buf[start..max_idx.min(start + count)].iter_mut() { 1224 *i = self.erase_char; 1225 } 1226 1227 if self.should_update() { 1228 self.do_update_region(start, count.min(max_idx - start)) 1229 } 1230 1231 self.need_wrap = false; 1232 } 1233 1234 fn t416_color(&mut self, mut idx: usize) -> (usize, Option<Color>) { 1235 idx += 1; 1236 if idx > self.npar as usize { 1237 return (idx, None); 1238 } 1239 1240 if self.par[idx] == 5 && idx < self.npar as usize { 1241 // 256色 1242 idx += 1; 1243 return (idx, Some(Color::from_256(self.par[idx]))); 1244 } else if self.par[idx] == 2 && idx + 3 <= self.npar as usize { 1245 // 24位 1246 let color = Color { 1247 red: self.par[idx + 1] as u16, 1248 green: self.par[idx + 2] as u16, 1249 blue: self.par[idx + 3] as u16, 1250 ..Default::default() 1251 }; 1252 idx += 3; 1253 return (idx, Some(color)); 1254 } else { 1255 return (idx, None); 1256 } 1257 } 1258 1259 /// ## 处理终端控制字符 1260 #[inline(never)] 1261 pub(super) fn do_control(&mut self, ch: u32) { 1262 // 首先检查是否处于 ANSI 控制字符串状态 1263 if self.vc_state.is_ansi_control_string() && (8..=13).contains(&ch) { 1264 return; 1265 } 1266 1267 match ch { 1268 0 => { 1269 return; 1270 } 1271 7 => { 1272 // BEL 1273 if self.vc_state.is_ansi_control_string() { 1274 self.vc_state = VirtualConsoleState::ESnormal; 1275 } 1276 // TODO: 发出声音? 1277 return; 1278 } 1279 8 => { 1280 // BS backspace 1281 self.backspace(); 1282 return; 1283 } 1284 9 => { 1285 // 水平制表符(Horizontal Tab) 1286 self.pos -= self.state.x; 1287 1288 let ret = self.tab_stop.next_index(self.state.x + 1); 1289 1290 if let Some(x) = ret { 1291 self.state.x = x; 1292 } else { 1293 self.state.x = self.cols - 1; 1294 } 1295 1296 self.pos += self.state.x; 1297 // TODO: notify 1298 return; 1299 } 1300 10..=12 => { 1301 // LD line feed 1302 self.line_feed(); 1303 // TODO: 检查键盘模式 1304 self.carriage_return(); 1305 return; 1306 } 1307 13 => { 1308 // CR 回车符 1309 self.carriage_return(); 1310 return; 1311 } 1312 14 => { 1313 todo!("Gx_charset todo!"); 1314 } 1315 15 => { 1316 todo!("Gx_charset todo!"); 1317 } 1318 24 | 26 => { 1319 self.vc_state = VirtualConsoleState::ESnormal; 1320 return; 1321 } 1322 27 => { 1323 // esc 1324 self.vc_state = VirtualConsoleState::ESesc; 1325 return; 1326 } 1327 127 => { 1328 // delete 1329 self.delete(); 1330 return; 1331 } 1332 155 => { 1333 // '[' 1334 self.vc_state = VirtualConsoleState::ESsquare; 1335 return; 1336 } 1337 _ => {} 1338 } 1339 1340 match self.vc_state { 1341 VirtualConsoleState::ESesc => { 1342 self.vc_state = VirtualConsoleState::ESnormal; 1343 match ch as u8 as char { 1344 '[' => { 1345 self.vc_state = VirtualConsoleState::ESsquare; 1346 } 1347 ']' => { 1348 self.vc_state = VirtualConsoleState::ESnonstd; 1349 } 1350 '_' => { 1351 self.vc_state = VirtualConsoleState::ESapc; 1352 } 1353 '^' => { 1354 self.vc_state = VirtualConsoleState::ESpm; 1355 } 1356 '%' => { 1357 self.vc_state = VirtualConsoleState::ESpercent; 1358 } 1359 'E' => { 1360 self.carriage_return(); 1361 self.line_feed(); 1362 } 1363 'M' => { 1364 self.reverse_index(); 1365 } 1366 'D' => { 1367 self.line_feed(); 1368 } 1369 'H' => { 1370 if self.state.x < 256 { 1371 self.tab_stop.set(self.state.x, true); 1372 } 1373 } 1374 'P' => { 1375 self.vc_state = VirtualConsoleState::ESdcs; 1376 } 1377 'Z' => { 1378 todo!("Respond ID todo!"); 1379 } 1380 '7' => self.saved_state = self.state.clone(), 1381 '8' => self.restore_cursor(), 1382 '(' => { 1383 self.vc_state = VirtualConsoleState::ESsetG0; 1384 } 1385 ')' => { 1386 self.vc_state = VirtualConsoleState::ESsetG1; 1387 } 1388 '#' => { 1389 self.vc_state = VirtualConsoleState::EShash; 1390 } 1391 'c' => { 1392 self.reset(true); 1393 } 1394 '>' => { 1395 todo!("clr_kbd todo"); 1396 } 1397 '=' => { 1398 todo!("set_kbd todo"); 1399 } 1400 _ => {} 1401 } 1402 } 1403 VirtualConsoleState::ESsquare => { 1404 for i in self.par.iter_mut() { 1405 *i = 0; 1406 } 1407 self.vc_state = VirtualConsoleState::ESgetpars; 1408 self.npar = 0; 1409 let c = ch as u8 as char; 1410 if c == '[' { 1411 self.vc_state = VirtualConsoleState::ESfunckey; 1412 return; 1413 } 1414 1415 match c { 1416 '?' => { 1417 self.private = Vt102_OP::Pdec; 1418 return; 1419 } 1420 '>' => { 1421 self.private = Vt102_OP::Pgt; 1422 return; 1423 } 1424 '=' => { 1425 self.private = Vt102_OP::Peq; 1426 return; 1427 } 1428 '<' => { 1429 self.private = Vt102_OP::Plt; 1430 return; 1431 } 1432 _ => {} 1433 } 1434 1435 self.private = Vt102_OP::Pecma; 1436 self.do_getpars(c); 1437 } 1438 VirtualConsoleState::ESgetpars => { 1439 let c = ch as u8 as char; 1440 self.do_getpars(c); 1441 } 1442 VirtualConsoleState::ESfunckey => { 1443 self.vc_state = VirtualConsoleState::ESnormal; 1444 return; 1445 } 1446 VirtualConsoleState::EShash => { 1447 self.vc_state = VirtualConsoleState::ESnormal; 1448 if ch as u8 as char == '8' { 1449 self.erase_char = (self.erase_char & 0xff00) | 'E' as u16; 1450 self.csi_J(2); 1451 self.erase_char = (self.erase_char & 0xff00) | ' ' as u16; 1452 self.do_update_region(0, self.screen_buf.len()); 1453 } 1454 return; 1455 } 1456 VirtualConsoleState::ESsetG0 => { 1457 todo!("SetGx todo"); 1458 } 1459 VirtualConsoleState::ESsetG1 => { 1460 todo!("SetGx todo"); 1461 } 1462 VirtualConsoleState::ESpercent => { 1463 self.vc_state = VirtualConsoleState::ESnormal; 1464 let c = ch as u8 as char; 1465 match c { 1466 '@' => { 1467 self.utf = false; 1468 return; 1469 } 1470 'G' | '8' => { 1471 self.utf = true; 1472 return; 1473 } 1474 _ => {} 1475 } 1476 return; 1477 } 1478 VirtualConsoleState::EScsiignore => { 1479 if (20..=0x3f).contains(&ch) { 1480 return; 1481 } 1482 self.vc_state = VirtualConsoleState::ESnormal; 1483 return; 1484 } 1485 VirtualConsoleState::ESnonstd => { 1486 let c = ch as u8 as char; 1487 if c == 'P' { 1488 for i in self.par.iter_mut() { 1489 *i = 0; 1490 } 1491 self.npar = 0; 1492 self.vc_state = VirtualConsoleState::ESpalette; 1493 return; 1494 } else if c == 'R' { 1495 self.reset_palette(); 1496 self.vc_state = VirtualConsoleState::ESnormal; 1497 } else if c.is_ascii_digit() { 1498 self.vc_state = VirtualConsoleState::ESosc; 1499 } else { 1500 self.vc_state = VirtualConsoleState::ESnormal; 1501 } 1502 } 1503 VirtualConsoleState::ESpalette => { 1504 let c = ch as u8 as char; 1505 if c.is_ascii_hexdigit() { 1506 self.npar += 1; 1507 self.par[self.npar as usize] = c.to_digit(16).unwrap(); 1508 1509 if self.npar == 7 { 1510 let mut i = self.par[0] as usize; 1511 let mut j = 0; 1512 self.palette[i].red = self.par[j] as u16; 1513 j += 1; 1514 self.palette[i].green = self.par[j] as u16; 1515 j += 1; 1516 self.palette[i].blue = self.par[j] as u16; 1517 j += 1; 1518 i += 1; 1519 self.palette[i].red = self.par[j] as u16; 1520 j += 1; 1521 self.palette[i].green = self.par[j] as u16; 1522 j += 1; 1523 self.palette[i].blue = self.par[j] as u16; 1524 self.set_palette(); 1525 self.vc_state = VirtualConsoleState::ESnormal; 1526 } 1527 } 1528 } 1529 VirtualConsoleState::ESosc => {} 1530 VirtualConsoleState::ESapc => {} 1531 VirtualConsoleState::ESpm => {} 1532 VirtualConsoleState::ESdcs => {} 1533 VirtualConsoleState::ESnormal => {} 1534 } 1535 } 1536 1537 #[inline(never)] 1538 pub(super) fn console_write_normal( 1539 &mut self, 1540 mut tc: u32, 1541 c: u32, 1542 draw: &mut DrawRegion, 1543 ) -> bool { 1544 let mut attr = self.attr; 1545 let himask = self.hi_font_mask; 1546 let charmask = if himask == 0 { 0xff } else { 0x1ff }; 1547 let mut width = 1; 1548 // 表示需不需要反转 1549 let mut invert = false; 1550 if self.utf && !self.display_ctrl && FontDesc::is_double_width(c) { 1551 width = 2; 1552 } 1553 1554 let tmp = self.unicode_to_index(tc); 1555 if tmp & (!charmask as i32) != 0 { 1556 if tmp == -1 || tmp == -2 { 1557 return false; 1558 } 1559 1560 // 未找到 1561 if (!self.utf || self.display_ctrl || c < 128) && c & !charmask == 0 { 1562 tc = c; 1563 } else { 1564 let tmp = self.unicode_to_index(0xfffd); 1565 if tmp < 0 { 1566 invert = true; 1567 let tmp = self.unicode_to_index('?' as u32); 1568 if tmp < 0 { 1569 tc = '?' as u32; 1570 } else { 1571 tc = tmp as u32; 1572 } 1573 1574 attr = self.invert_attr(); 1575 self.flush(draw); 1576 } 1577 } 1578 } 1579 1580 loop { 1581 if self.need_wrap || self.insert_mode { 1582 self.flush(draw); 1583 } 1584 if self.need_wrap { 1585 self.carriage_return(); 1586 self.line_feed(); 1587 } 1588 1589 if self.insert_mode { 1590 self.insert_char(1); 1591 } 1592 1593 // TODO: 处理unicode screen buf 1594 1595 if himask != 0 { 1596 tc = (if tc & 0x100 != 0 { himask as u32 } else { 0 }) | (tc & 0xff); 1597 } 1598 1599 tc |= ((attr as u32) << 8) & (!himask as u32); 1600 1601 // kwarn!( 1602 // "ch {} pos {} x {} y {} cols {}", 1603 // c as u8 as char, 1604 // self.pos, 1605 // self.state.x, 1606 // self.state.y, 1607 // self.cols, 1608 // ); 1609 self.screen_buf[self.pos] = tc as u16; 1610 1611 if draw.x.is_none() { 1612 // 设置draw参数 1613 draw.x = Some(self.state.x as u32); 1614 draw.offset = self.pos; 1615 } 1616 1617 if self.state.x == self.cols - 1 { 1618 // 需要换行? 1619 self.need_wrap = self.autowrap; 1620 draw.size += 1; 1621 } else { 1622 self.state.x += 1; 1623 self.pos += 1; 1624 draw.size += 1; 1625 } 1626 1627 width -= 1; 1628 if width == 0 { 1629 break; 1630 } 1631 let tmp = self.unicode_to_index(' ' as u32); 1632 tc = if tmp < 0 { ' ' as u32 } else { tmp as u32 }; 1633 } 1634 1635 if invert { 1636 self.flush(draw); 1637 } 1638 1639 true 1640 } 1641 1642 /// ## 当前vc插入nr个字符 1643 fn insert_char(&mut self, nr: usize) { 1644 // TODO: 管理unicode屏幕信息 1645 1646 let pos = self.pos; 1647 // 把当前位置以后得字符向后移动nr*2位 1648 self.screen_buf[pos..].rotate_right(nr * 2); 1649 1650 // 把空出来的位置用erase_char填充 1651 for c in &mut self.screen_buf[pos..(pos + nr * 2)] { 1652 *c = self.erase_char 1653 } 1654 1655 self.need_wrap = false; 1656 1657 // 更新本行后面部分 1658 self.do_update_region(self.pos, self.cols - self.state.x); 1659 } 1660 1661 /// ## 更新虚拟控制台指定区域的显示 1662 fn do_update_region(&self, mut start: usize, mut count: usize) { 1663 let ret = self.driver_funcs().con_getxy(self, start); 1664 let (mut x, mut y) = if let Ok((_, tmp_x, tmp_y)) = ret { 1665 // start = tmp_start; 1666 (tmp_x, tmp_y) 1667 } else { 1668 (start % self.cols, start / self.cols) 1669 }; 1670 1671 loop { 1672 // 记录当前字符的属性 1673 let mut attr = self.screen_buf[start] & 0xff00; 1674 let mut startx = x; 1675 let mut size = 0; 1676 1677 while count != 0 && x < self.cols { 1678 // 检查属性是否变化,如果属性变了,则将前一个字符先输出 1679 if attr != (self.screen_buf[start] & 0xff00) && size > 0 { 1680 let _ = self.driver_funcs().con_putcs( 1681 self, 1682 &self.screen_buf[start..], 1683 size, 1684 y as u32, 1685 startx as u32, 1686 ); 1687 startx = x; 1688 start += size; 1689 size = 0; 1690 attr = self.screen_buf[start] & 0xff00; 1691 } 1692 size += 1; 1693 x += 1; 1694 count -= 1; 1695 } 1696 1697 if size > 0 { 1698 let _ = self.driver_funcs().con_putcs( 1699 self, 1700 &self.screen_buf[start..], 1701 size, 1702 y as u32, 1703 startx as u32, 1704 ); 1705 } 1706 if count == 0 { 1707 break; 1708 } 1709 1710 // 一行 1711 x = 0; 1712 y += 1; 1713 1714 let ret = self.driver_funcs().con_getxy(self, start); 1715 if let Ok(ret) = ret { 1716 start = ret.0; 1717 } else { 1718 return; 1719 } 1720 } 1721 } 1722 1723 const UNI_DIRECT_MAKS: u32 = 0x01ff; 1724 const UNI_DIRECT_BASE: u32 = 0xf000; 1725 /// ## unicode字符转对应的坐标,暂时这样写,还没有适配unicode 1726 /// 这里是糊代码的,后面重写 1727 fn unicode_to_index(&self, ch: u32) -> i32 { 1728 if ch > 0xfff { 1729 // 未找到 1730 return -4; 1731 } else if ch < 0x20 { 1732 // 不可打印 1733 return -1; 1734 } else if ch == 0xfeff || (0x200b..=0x200f).contains(&ch) { 1735 // 零长空格 1736 return -2; 1737 } else if (ch & !Self::UNI_DIRECT_MAKS) == Self::UNI_DIRECT_BASE { 1738 return (ch & Self::UNI_DIRECT_MAKS) as i32; 1739 } 1740 1741 // TODO: 暂时这样写,表示不支持 1742 return -3; 1743 } 1744 1745 fn invert_attr(&self) -> u8 { 1746 if !self.color_mode { 1747 return self.attr ^ 0x08; 1748 } 1749 1750 if self.hi_font_mask == 0x100 { 1751 return (self.attr & 0x11) | ((self.attr & 0xe0) >> 4) | ((self.attr & 0x0e) << 4); 1752 } 1753 1754 return (self.attr & 0x88) | ((self.attr & 0x70) >> 4) | ((self.attr & 0x07) << 4); 1755 } 1756 1757 pub(super) fn flush(&self, draw: &mut DrawRegion) { 1758 if draw.x.is_none() { 1759 return; 1760 } 1761 1762 let _ = self.driver_funcs().con_putcs( 1763 self, 1764 &self.screen_buf[draw.offset..draw.offset + draw.size], 1765 draw.size, 1766 self.state.y as u32, 1767 draw.x.unwrap(), 1768 ); 1769 1770 draw.x = None; 1771 draw.size = 0; 1772 } 1773 1774 fn build_attr( 1775 &self, 1776 color: u8, 1777 intensity: VirtualConsoleIntensity, 1778 blink: bool, 1779 underline: bool, 1780 reverse: bool, 1781 italic: bool, 1782 ) -> u8 { 1783 let ret = self 1784 .driver_funcs() 1785 .con_build_attr(self, color, intensity, blink, underline, reverse, italic); 1786 1787 if let Ok(ret) = ret { 1788 return ret; 1789 } 1790 1791 let mut ret = color; 1792 1793 if !self.color_mode { 1794 return intensity as u8 1795 | (italic as u8) << 1 1796 | (underline as u8) << 2 1797 | (reverse as u8) << 3 1798 | (blink as u8) << 7; 1799 } 1800 1801 if italic { 1802 ret = (ret & 0xf0) | self.italic_color as u8; 1803 } else if underline { 1804 ret = (ret & 0xf0) | self.underline_color as u8; 1805 } else if intensity == VirtualConsoleIntensity::HalfBright { 1806 ret = (ret & 0xf0) | self.half_color as u8; 1807 } 1808 1809 if reverse { 1810 ret = (ret & 0x88) | (((ret >> 4) | (ret << 4)) & 0x77); 1811 } 1812 1813 if blink { 1814 ret ^= 0x80; 1815 } 1816 1817 if intensity == VirtualConsoleIntensity::Bold { 1818 ret ^= 0x08; 1819 } 1820 1821 if self.hi_font_mask == 0x100 { 1822 ret <<= 1; 1823 } 1824 1825 ret 1826 } 1827 1828 pub(super) fn update_attr(&mut self) { 1829 self.attr = self.build_attr( 1830 self.state.color, 1831 self.state.intensity, 1832 self.state.blink, 1833 self.state.underline, 1834 self.state.reverse ^ self.screen_mode, 1835 self.state.italic, 1836 ); 1837 1838 self.erase_char = ' ' as u16 1839 | ((self.build_attr( 1840 self.state.color, 1841 VirtualConsoleIntensity::Normal, 1842 self.state.blink, 1843 false, 1844 self.screen_mode, 1845 false, 1846 ) as u16) 1847 << 8); 1848 } 1849 1850 fn default_attr(&mut self) { 1851 self.state.intensity = VirtualConsoleIntensity::Normal; 1852 self.state.italic = false; 1853 self.state.underline = false; 1854 self.state.reverse = false; 1855 self.state.blink = false; 1856 self.state.color = self.def_color; 1857 } 1858 } 1859 1860 /// ## 虚拟控制台的状态信息 1861 #[derive(Debug, Default, Clone)] 1862 pub struct VirtualConsoleInfo { 1863 // x,y表示光标坐标 1864 pub x: usize, 1865 pub y: usize, 1866 pub color: u8, 1867 1868 /// 表示字符的强度 1869 intensity: VirtualConsoleIntensity, 1870 /// 斜体 1871 italic: bool, 1872 /// 下划线 1873 underline: bool, 1874 /// 字符闪烁 1875 blink: bool, 1876 /// 前景与背景色反转 1877 reverse: bool, 1878 } 1879 1880 impl VirtualConsoleInfo { 1881 pub fn new(x: usize, y: usize) -> Self { 1882 Self { 1883 x, 1884 y, 1885 color: Default::default(), 1886 intensity: Default::default(), 1887 italic: Default::default(), 1888 underline: Default::default(), 1889 blink: Default::default(), 1890 reverse: Default::default(), 1891 } 1892 } 1893 } 1894 1895 /// 字符强度 1896 #[derive(Debug, Clone, PartialEq, Copy)] 1897 pub enum VirtualConsoleIntensity { 1898 /// 暗淡 1899 HalfBright = 0, 1900 /// 正常 1901 Normal = 1, 1902 /// 粗体 1903 Bold = 2, 1904 } 1905 1906 impl Default for VirtualConsoleIntensity { 1907 fn default() -> Self { 1908 Self::Normal 1909 } 1910 } 1911 1912 /// ## 虚拟控制台的状态 1913 /// 1914 /// 可以把VC的接收字符理解为一个状态机 1915 #[derive(Debug, PartialEq, Clone)] 1916 pub enum VirtualConsoleState { 1917 /// 正常状态 1918 ESnormal, 1919 /// 收到了转义字符 \e,即"Escape"字符 1920 ESesc, 1921 /// 收到了 "[" 字符,通常是 ANSI 控制序列的开始 1922 ESsquare, 1923 /// 解析参数状态 1924 ESgetpars, 1925 /// 功能键状态 1926 ESfunckey, 1927 /// 收到了 "#" 字符 1928 EShash, 1929 /// 设置 G0 字符集状态 1930 ESsetG0, 1931 /// 设置 G1 字符集状态 1932 ESsetG1, 1933 /// 收到了 "%" 字符 1934 ESpercent, 1935 /// 忽略 ANSI 控制序列状态 1936 EScsiignore, 1937 /// 非标准字符状态 1938 ESnonstd, 1939 /// 调色板状态 1940 ESpalette, 1941 /// Operating System Command (OSC) 状态 1942 ESosc, 1943 /// Application Program Command (APC) 状态 1944 ESapc, 1945 /// Privacy Message (PM) 状态 1946 ESpm, 1947 /// Device Control String (DCS) 状态 1948 ESdcs, 1949 } 1950 1951 impl VirtualConsoleState { 1952 pub fn is_ansi_control_string(&self) -> bool { 1953 if *self == Self::ESosc 1954 || *self == Self::ESapc 1955 || *self == Self::ESpm 1956 || *self == Self::ESdcs 1957 { 1958 return true; 1959 } 1960 1961 false 1962 } 1963 } 1964 1965 #[derive(Debug, Clone, PartialEq, PartialOrd)] 1966 #[allow(non_camel_case_types)] 1967 pub enum Vt102_OP { 1968 Pecma, 1969 Pdec, 1970 Peq, 1971 Pgt, 1972 Plt, 1973 } 1974 1975 bitflags! { 1976 #[derive(Default)] 1977 pub struct VcCursor: u32 { 1978 /// 默认 1979 const CUR_DEF = 0; 1980 /// 无光标 1981 const CUR_NONE = 1; 1982 /// 下划线形式 1983 const CUR_UNDERLINE = 2; 1984 /// 光标占据底部的三分之一 1985 const CUR_LOWER_THIRD = 3; 1986 /// 光标占据底部的一半 1987 const CUR_LOWER_HALF = 4; 1988 /// 光标占据底部的三分之二 1989 const CUR_TWO_THIRDS = 5; 1990 /// 光标为块状(方块)形式 1991 const CUR_BLOCK = 6; 1992 /// 光标属性,用于指示软件光标 1993 const CUR_SW = 0x000010; 1994 /// 光标属性,用于指示光标是否始终在背景上显示 1995 const CUR_ALWAYS_BG = 0x000020; 1996 /// 光标属性,用于指示前景和背景是否反转 1997 const CUR_INVERT_FG_BG = 0x000040; 1998 /// 光标前景色属性,用于指定光标的前景色 1999 const CUR_FG = 0x000700; 2000 /// 光标背景色属性,用于指定光标的背景色 2001 const CUR_BG = 0x007000; 2002 } 2003 } 2004 2005 impl VcCursor { 2006 pub fn make_cursor(size: u32, change: u32, set: u32) -> Self { 2007 unsafe { Self::from_bits_unchecked(size | (change << 8) | (set << 16)) } 2008 } 2009 2010 pub fn cursor_size(&self) -> Self { 2011 Self::from_bits_truncate(self.bits & 0x00000f) 2012 } 2013 2014 pub fn cursor_set(&self) -> u32 { 2015 (self.bits & 0xff0000) >> 8 2016 } 2017 2018 pub fn cursor_change(&self) -> u32 { 2019 self.bits & 0x00ff00 2020 } 2021 } 2022 2023 #[derive(Debug, PartialEq)] 2024 #[allow(dead_code)] 2025 pub enum CursorOperation { 2026 Draw, 2027 Erase, 2028 Move, 2029 } 2030 2031 #[derive(Debug, PartialEq, Clone, Copy)] 2032 pub enum ScrollDir { 2033 Up, 2034 Down, 2035 } 2036