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