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