1abe3a6eaShanjiezhou use crate::{ 21496ba7bSLoGin driver::{ 352da9a59SGnoCiYeH serial::serial8250::send_to_default_serial8250_port, 4dfe53cf0SGnoCiYeH tty::{tty_port::tty_port, virtual_terminal::virtual_console::CURRENT_VCNUM}, 552da9a59SGnoCiYeH video::video_refresh_manager, 61496ba7bSLoGin }, 71496ba7bSLoGin kdebug, kinfo, 81496ba7bSLoGin libs::{ 91496ba7bSLoGin lib_ui::font::FONT_8x16, 101496ba7bSLoGin rwlock::RwLock, 111496ba7bSLoGin spinlock::{SpinLock, SpinLockGuard}, 121496ba7bSLoGin }, 13abe3a6eaShanjiezhou }; 14abe3a6eaShanjiezhou use alloc::{boxed::Box, collections::LinkedList, string::ToString}; 15abe3a6eaShanjiezhou use alloc::{sync::Arc, vec::Vec}; 16abe3a6eaShanjiezhou use core::{ 17abe3a6eaShanjiezhou fmt::Debug, 18abe3a6eaShanjiezhou intrinsics::unlikely, 19abe3a6eaShanjiezhou ops::{Add, AddAssign, Sub}, 202755467cS曾俊 ptr::copy_nonoverlapping, 21abe3a6eaShanjiezhou sync::atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering}, 22abe3a6eaShanjiezhou }; 2391e9d4abSLoGin use system_error::SystemError; 24abe3a6eaShanjiezhou 25abe3a6eaShanjiezhou use super::{ 26abe3a6eaShanjiezhou screen_manager::{ 271496ba7bSLoGin scm_register, ScmBuffer, ScmBufferInfo, ScmFramworkType, ScmUiFramework, 281496ba7bSLoGin ScmUiFrameworkMetadata, 29abe3a6eaShanjiezhou }, 30abe3a6eaShanjiezhou textui_no_alloc::no_init_textui_putchar_window, 31abe3a6eaShanjiezhou }; 32abe3a6eaShanjiezhou 33abe3a6eaShanjiezhou /// 声明全局的TEXTUI_FRAMEWORK 341496ba7bSLoGin static mut __TEXTUI_FRAMEWORK: Option<Arc<TextUiFramework>> = None; 35abe3a6eaShanjiezhou 36abe3a6eaShanjiezhou /// 每个字符的宽度和高度(像素) 37abe3a6eaShanjiezhou pub const TEXTUI_CHAR_WIDTH: u32 = 8; 38abe3a6eaShanjiezhou 39abe3a6eaShanjiezhou pub const TEXTUI_CHAR_HEIGHT: u32 = 16; 40abe3a6eaShanjiezhou 41abe3a6eaShanjiezhou pub static mut TEXTUI_IS_INIT: bool = false; 42abe3a6eaShanjiezhou 431a72a751SLoGin static ENABLE_PUT_TO_WINDOW: AtomicBool = AtomicBool::new(false); 441a72a751SLoGin 451a72a751SLoGin /// 启用将文本输出到窗口的功能。 461a72a751SLoGin pub fn textui_enable_put_to_window() { 471a72a751SLoGin ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst); 481a72a751SLoGin } 491a72a751SLoGin 501a72a751SLoGin /// 禁用将文本输出到窗口的功能。 511a72a751SLoGin pub fn textui_disable_put_to_window() { 521a72a751SLoGin ENABLE_PUT_TO_WINDOW.store(false, Ordering::SeqCst); 531a72a751SLoGin } 541a72a751SLoGin 551a72a751SLoGin /// 检查是否启用了将文本输出到窗口的功能。 561a72a751SLoGin /// 571a72a751SLoGin /// # 返回 581a72a751SLoGin /// 如果启用了将文本输出到窗口的功能,则返回 `true`,否则返回 `false`。 591a72a751SLoGin pub fn textui_is_enable_put_to_window() -> bool { 601a72a751SLoGin ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst) 611a72a751SLoGin } 62abe3a6eaShanjiezhou 63abe3a6eaShanjiezhou /// 获取TEXTUI_FRAMEWORK的可变实例 641496ba7bSLoGin pub fn textui_framework() -> Arc<TextUiFramework> { 651496ba7bSLoGin unsafe { 661496ba7bSLoGin return __TEXTUI_FRAMEWORK 671496ba7bSLoGin .as_ref() 681496ba7bSLoGin .expect("Textui framework has not been initialized yet!") 691496ba7bSLoGin .clone(); 70abe3a6eaShanjiezhou } 711496ba7bSLoGin } 721496ba7bSLoGin 73abe3a6eaShanjiezhou /// 初始化TEXTUI_FRAMEWORK 745b59005fSLoGin fn textui_framwork_init() { 755b59005fSLoGin if unsafe { __TEXTUI_FRAMEWORK.is_none() } { 76abe3a6eaShanjiezhou kinfo!("textuiframework init"); 77abe3a6eaShanjiezhou let metadata = ScmUiFrameworkMetadata::new("TextUI".to_string(), ScmFramworkType::Text); 781496ba7bSLoGin kdebug!("textui metadata: {:?}", metadata); 79abe3a6eaShanjiezhou // 为textui框架生成第一个窗口 801496ba7bSLoGin let vlines_num = (metadata.buf_info().height() / TEXTUI_CHAR_HEIGHT) as usize; 81abe3a6eaShanjiezhou 821496ba7bSLoGin let chars_num = (metadata.buf_info().width() / TEXTUI_CHAR_WIDTH) as usize; 83abe3a6eaShanjiezhou 84abe3a6eaShanjiezhou let initial_window = TextuiWindow::new( 85abe3a6eaShanjiezhou WindowFlag::TEXTUI_CHROMATIC, 86abe3a6eaShanjiezhou vlines_num as i32, 87abe3a6eaShanjiezhou chars_num as i32, 88abe3a6eaShanjiezhou ); 89abe3a6eaShanjiezhou 90abe3a6eaShanjiezhou let current_window: Arc<SpinLock<TextuiWindow>> = Arc::new(SpinLock::new(initial_window)); 91abe3a6eaShanjiezhou 92abe3a6eaShanjiezhou let default_window = current_window.clone(); 93abe3a6eaShanjiezhou 94abe3a6eaShanjiezhou // 生成窗口链表,并把上面窗口添加进textui框架的窗口链表中 95abe3a6eaShanjiezhou let window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>> = 96abe3a6eaShanjiezhou Arc::new(SpinLock::new(LinkedList::new())); 97abe3a6eaShanjiezhou window_list.lock().push_back(current_window.clone()); 98abe3a6eaShanjiezhou 995b59005fSLoGin unsafe { 1001496ba7bSLoGin __TEXTUI_FRAMEWORK = Some(Arc::new(TextUiFramework::new( 101abe3a6eaShanjiezhou metadata, 102abe3a6eaShanjiezhou window_list, 103abe3a6eaShanjiezhou current_window, 104abe3a6eaShanjiezhou default_window, 1055b59005fSLoGin ))) 1065b59005fSLoGin }; 1071496ba7bSLoGin 1081496ba7bSLoGin scm_register(textui_framework()).expect("register textui framework failed"); 1091496ba7bSLoGin kdebug!("textui framework init success"); 1101496ba7bSLoGin 111a03c4f9dSLoGin send_to_default_serial8250_port("\ntext ui initialized\n\0".as_bytes()); 1121496ba7bSLoGin unsafe { TEXTUI_IS_INIT = true }; 113abe3a6eaShanjiezhou } else { 114abe3a6eaShanjiezhou panic!("Try to init TEXTUI_FRAMEWORK twice!"); 115abe3a6eaShanjiezhou } 116abe3a6eaShanjiezhou } 117abe3a6eaShanjiezhou // window标志位 118abe3a6eaShanjiezhou bitflags! { 119abe3a6eaShanjiezhou pub struct WindowFlag: u8 { 120abe3a6eaShanjiezhou // 采用彩色字符 121abe3a6eaShanjiezhou const TEXTUI_CHROMATIC = 1 << 0; 122abe3a6eaShanjiezhou } 123abe3a6eaShanjiezhou } 124abe3a6eaShanjiezhou 125abe3a6eaShanjiezhou /** 126abe3a6eaShanjiezhou * @brief 黑白字符对象 127abe3a6eaShanjiezhou * 128abe3a6eaShanjiezhou */ 129abe3a6eaShanjiezhou #[derive(Clone, Debug)] 130abe3a6eaShanjiezhou struct TextuiCharNormal { 131abe3a6eaShanjiezhou _data: u8, 132abe3a6eaShanjiezhou } 133abe3a6eaShanjiezhou 134abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)] 135abe3a6eaShanjiezhou pub struct LineId(i32); 136abe3a6eaShanjiezhou impl LineId { 137abe3a6eaShanjiezhou pub fn new(num: i32) -> Self { 138abe3a6eaShanjiezhou LineId(num) 139abe3a6eaShanjiezhou } 140abe3a6eaShanjiezhou 141abe3a6eaShanjiezhou pub fn check(&self, max: i32) -> bool { 142abe3a6eaShanjiezhou self.0 < max && self.0 >= 0 143abe3a6eaShanjiezhou } 144abe3a6eaShanjiezhou 145abe3a6eaShanjiezhou pub fn data(&self) -> i32 { 146abe3a6eaShanjiezhou self.0 147abe3a6eaShanjiezhou } 148abe3a6eaShanjiezhou } 149abe3a6eaShanjiezhou impl Add<i32> for LineId { 150abe3a6eaShanjiezhou type Output = LineId; 151abe3a6eaShanjiezhou fn add(self, rhs: i32) -> Self::Output { 152abe3a6eaShanjiezhou LineId::new(self.0 + rhs) 153abe3a6eaShanjiezhou } 154abe3a6eaShanjiezhou } 155abe3a6eaShanjiezhou impl Sub<i32> for LineId { 156abe3a6eaShanjiezhou type Output = LineId; 157abe3a6eaShanjiezhou 158abe3a6eaShanjiezhou fn sub(self, rhs: i32) -> Self::Output { 159abe3a6eaShanjiezhou LineId::new(self.0 - rhs) 160abe3a6eaShanjiezhou } 161abe3a6eaShanjiezhou } 162b5b571e0SLoGin impl From<LineId> for i32 { 163b5b571e0SLoGin fn from(value: LineId) -> Self { 164b5b571e0SLoGin value.0 165abe3a6eaShanjiezhou } 166abe3a6eaShanjiezhou } 167b5b571e0SLoGin impl From<LineId> for u32 { 168b5b571e0SLoGin fn from(value: LineId) -> Self { 169b5b571e0SLoGin value.0 as u32 170abe3a6eaShanjiezhou } 171abe3a6eaShanjiezhou } 172b5b571e0SLoGin impl From<LineId> for usize { 173b5b571e0SLoGin fn from(value: LineId) -> Self { 174b5b571e0SLoGin value.0 as usize 175abe3a6eaShanjiezhou } 176abe3a6eaShanjiezhou } 177abe3a6eaShanjiezhou impl Sub<LineId> for LineId { 178abe3a6eaShanjiezhou type Output = LineId; 179abe3a6eaShanjiezhou 180abe3a6eaShanjiezhou fn sub(mut self, rhs: LineId) -> Self::Output { 181abe3a6eaShanjiezhou self.0 -= rhs.0; 182abe3a6eaShanjiezhou return self; 183abe3a6eaShanjiezhou } 184abe3a6eaShanjiezhou } 185abe3a6eaShanjiezhou impl AddAssign<LineId> for LineId { 186abe3a6eaShanjiezhou fn add_assign(&mut self, rhs: LineId) { 187abe3a6eaShanjiezhou self.0 += rhs.0; 188abe3a6eaShanjiezhou } 189abe3a6eaShanjiezhou } 190abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)] 191abe3a6eaShanjiezhou pub struct LineIndex(i32); 192abe3a6eaShanjiezhou impl LineIndex { 193abe3a6eaShanjiezhou pub fn new(num: i32) -> Self { 194abe3a6eaShanjiezhou LineIndex(num) 195abe3a6eaShanjiezhou } 196abe3a6eaShanjiezhou pub fn check(&self, chars_per_line: i32) -> bool { 197abe3a6eaShanjiezhou self.0 < chars_per_line && self.0 >= 0 198abe3a6eaShanjiezhou } 199abe3a6eaShanjiezhou } 200abe3a6eaShanjiezhou impl Add<LineIndex> for LineIndex { 201abe3a6eaShanjiezhou type Output = LineIndex; 202abe3a6eaShanjiezhou 203abe3a6eaShanjiezhou fn add(self, rhs: LineIndex) -> Self::Output { 204abe3a6eaShanjiezhou LineIndex::new(self.0 + rhs.0) 205abe3a6eaShanjiezhou } 206abe3a6eaShanjiezhou } 207abe3a6eaShanjiezhou impl Add<i32> for LineIndex { 208abe3a6eaShanjiezhou // type Output = Self; 209abe3a6eaShanjiezhou type Output = LineIndex; 210abe3a6eaShanjiezhou 211abe3a6eaShanjiezhou fn add(self, rhs: i32) -> Self::Output { 212abe3a6eaShanjiezhou LineIndex::new(self.0 + rhs) 213abe3a6eaShanjiezhou } 214abe3a6eaShanjiezhou } 215abe3a6eaShanjiezhou impl Sub<i32> for LineIndex { 216abe3a6eaShanjiezhou type Output = LineIndex; 217abe3a6eaShanjiezhou 218abe3a6eaShanjiezhou fn sub(self, rhs: i32) -> Self::Output { 219abe3a6eaShanjiezhou LineIndex::new(self.0 - rhs) 220abe3a6eaShanjiezhou } 221abe3a6eaShanjiezhou } 222abe3a6eaShanjiezhou 223b5b571e0SLoGin impl From<LineIndex> for i32 { 224b5b571e0SLoGin fn from(val: LineIndex) -> Self { 225b5b571e0SLoGin val.0 226abe3a6eaShanjiezhou } 227abe3a6eaShanjiezhou } 228b5b571e0SLoGin impl From<LineIndex> for u32 { 229b5b571e0SLoGin fn from(value: LineIndex) -> Self { 230b5b571e0SLoGin value.0 as u32 231abe3a6eaShanjiezhou } 232abe3a6eaShanjiezhou } 233b5b571e0SLoGin impl From<LineIndex> for usize { 234b5b571e0SLoGin fn from(value: LineIndex) -> Self { 235b5b571e0SLoGin value.0 as usize 236abe3a6eaShanjiezhou } 237abe3a6eaShanjiezhou } 238abe3a6eaShanjiezhou #[derive(Copy, Clone, Debug)] 239abe3a6eaShanjiezhou pub struct FontColor(u32); 240abe3a6eaShanjiezhou #[allow(dead_code)] 241abe3a6eaShanjiezhou impl FontColor { 242abe3a6eaShanjiezhou pub const BLUE: FontColor = FontColor::new(0, 0, 0xff); 243abe3a6eaShanjiezhou pub const RED: FontColor = FontColor::new(0xff, 0, 0); 244abe3a6eaShanjiezhou pub const GREEN: FontColor = FontColor::new(0, 0xff, 0); 245abe3a6eaShanjiezhou pub const WHITE: FontColor = FontColor::new(0xff, 0xff, 0xff); 246abe3a6eaShanjiezhou pub const BLACK: FontColor = FontColor::new(0, 0, 0); 247abe3a6eaShanjiezhou pub const YELLOW: FontColor = FontColor::new(0xff, 0xff, 0); 248abe3a6eaShanjiezhou pub const ORANGE: FontColor = FontColor::new(0xff, 0x80, 0); 249abe3a6eaShanjiezhou pub const INDIGO: FontColor = FontColor::new(0x00, 0xff, 0xff); 250abe3a6eaShanjiezhou pub const PURPLE: FontColor = FontColor::new(0x80, 0x00, 0xff); 251abe3a6eaShanjiezhou 252abe3a6eaShanjiezhou pub const fn new(r: u8, g: u8, b: u8) -> Self { 253abe3a6eaShanjiezhou let val = ((r as u32) << 16) | ((g as u32) << 8) | (b as u32); 254abe3a6eaShanjiezhou return FontColor(val & 0x00ffffff); 255abe3a6eaShanjiezhou } 256abe3a6eaShanjiezhou } 257abe3a6eaShanjiezhou 258abe3a6eaShanjiezhou impl From<u32> for FontColor { 259abe3a6eaShanjiezhou fn from(value: u32) -> Self { 260abe3a6eaShanjiezhou return Self(value & 0x00ffffff); 261abe3a6eaShanjiezhou } 262abe3a6eaShanjiezhou } 263b5b571e0SLoGin impl From<FontColor> for usize { 264b5b571e0SLoGin fn from(value: FontColor) -> Self { 265b5b571e0SLoGin value.0 as usize 266abe3a6eaShanjiezhou } 267abe3a6eaShanjiezhou } 268b5b571e0SLoGin impl From<FontColor> for u32 { 269b5b571e0SLoGin fn from(value: FontColor) -> Self { 270b5b571e0SLoGin value.0 271abe3a6eaShanjiezhou } 272abe3a6eaShanjiezhou } 273b5b571e0SLoGin impl From<FontColor> for u16 { 274b5b571e0SLoGin fn from(value: FontColor) -> Self { 275b5b571e0SLoGin value.0 as u16 276abe3a6eaShanjiezhou } 277abe3a6eaShanjiezhou } 278b5b571e0SLoGin impl From<FontColor> for u64 { 279b5b571e0SLoGin fn from(value: FontColor) -> Self { 280b5b571e0SLoGin value.0 as u64 281abe3a6eaShanjiezhou } 282abe3a6eaShanjiezhou } 283abe3a6eaShanjiezhou 284abe3a6eaShanjiezhou /// 彩色字符对象 285abe3a6eaShanjiezhou 286abe3a6eaShanjiezhou #[derive(Clone, Debug, Copy)] 287abe3a6eaShanjiezhou pub struct TextuiCharChromatic { 288abe3a6eaShanjiezhou c: Option<char>, 289abe3a6eaShanjiezhou 290abe3a6eaShanjiezhou // 前景色 291abe3a6eaShanjiezhou frcolor: FontColor, // rgb 292abe3a6eaShanjiezhou 293abe3a6eaShanjiezhou // 背景色 294abe3a6eaShanjiezhou bkcolor: FontColor, // rgb 295abe3a6eaShanjiezhou } 296abe3a6eaShanjiezhou 297abe3a6eaShanjiezhou #[derive(Debug)] 2981496ba7bSLoGin pub struct TextuiBuf<'a> { 2992755467cS曾俊 buf: Option<&'a mut [u8]>, 3002755467cS曾俊 3012755467cS曾俊 guard: Option<SpinLockGuard<'a, Box<[u8]>>>, 3022755467cS曾俊 3032755467cS曾俊 bit_depth: u32, 3041496ba7bSLoGin } 305abe3a6eaShanjiezhou 306abe3a6eaShanjiezhou impl TextuiBuf<'_> { 3071496ba7bSLoGin pub fn new(buf: &mut ScmBufferInfo) -> TextuiBuf { 3081496ba7bSLoGin let len = buf.buf_size() / 4; 3092755467cS曾俊 let depth = video_refresh_manager().device_buffer().bit_depth(); 3101496ba7bSLoGin match &buf.buf { 3111496ba7bSLoGin ScmBuffer::DeviceBuffer(vaddr) => { 3121496ba7bSLoGin return TextuiBuf { 3131496ba7bSLoGin buf: Some(unsafe { 3142755467cS曾俊 core::slice::from_raw_parts_mut(vaddr.data() as *mut u8, len) 3151496ba7bSLoGin }), 3161496ba7bSLoGin guard: None, 3172755467cS曾俊 bit_depth: depth, 3181496ba7bSLoGin }; 3191496ba7bSLoGin } 3201496ba7bSLoGin 3211496ba7bSLoGin ScmBuffer::DoubleBuffer(double_buffer) => { 3222755467cS曾俊 let guard: SpinLockGuard<'_, Box<[u8]>> = double_buffer.lock(); 3231496ba7bSLoGin 3241496ba7bSLoGin return TextuiBuf { 3251496ba7bSLoGin buf: None, 3261496ba7bSLoGin guard: Some(guard), 3272755467cS曾俊 bit_depth: depth, 3281496ba7bSLoGin }; 3291496ba7bSLoGin } 3301496ba7bSLoGin } 3311496ba7bSLoGin } 3321496ba7bSLoGin 3332755467cS曾俊 pub fn buf_mut(&mut self) -> &mut [u8] { 3341496ba7bSLoGin if let Some(buf) = &mut self.buf { 3351496ba7bSLoGin return buf; 3361496ba7bSLoGin } else { 3371496ba7bSLoGin return self.guard.as_mut().unwrap().as_mut(); 3381496ba7bSLoGin } 339abe3a6eaShanjiezhou } 340*3959e94dS曾俊 341abe3a6eaShanjiezhou pub fn put_color_in_pixel(&mut self, color: u32, index: usize) { 3422755467cS曾俊 let index = index as isize; 3432755467cS曾俊 match self.bit_depth { 3442755467cS曾俊 32 => { 3452755467cS曾俊 let buf = self.buf_mut().as_mut_ptr() as *mut u32; 3462755467cS曾俊 unsafe { 3472755467cS曾俊 *buf.offset(index) = color; 3482755467cS曾俊 } 3492755467cS曾俊 } 3502755467cS曾俊 24 => { 3512755467cS曾俊 let buf = self.buf_mut().as_mut_ptr(); 3522755467cS曾俊 unsafe { 3532755467cS曾俊 copy_nonoverlapping(&color as *const u32 as *const u8, buf.offset(index * 3), 3) 3542755467cS曾俊 }; 3552755467cS曾俊 } 3562755467cS曾俊 16 => { 3572755467cS曾俊 let buf = self.buf_mut().as_mut_ptr(); 3582755467cS曾俊 unsafe { 3592755467cS曾俊 copy_nonoverlapping( 3602755467cS曾俊 &color as *const u32 as *const u8, 3612755467cS曾俊 buf.offset(index * 2), 3622755467cS曾俊 2, 3632755467cS曾俊 ); 3642755467cS曾俊 }; 3652755467cS曾俊 } 3662755467cS曾俊 _ => { 367*3959e94dS曾俊 panic!("bidepth unsupported!") 3682755467cS曾俊 } 3692755467cS曾俊 } 370abe3a6eaShanjiezhou } 371abe3a6eaShanjiezhou pub fn get_index_of_next_line(now_index: usize) -> usize { 3721496ba7bSLoGin textui_framework().metadata.read().buf_info().width() as usize + now_index 373abe3a6eaShanjiezhou } 374abe3a6eaShanjiezhou pub fn get_index_by_x_y(x: usize, y: usize) -> usize { 3751496ba7bSLoGin textui_framework().metadata.read().buf_info().width() as usize * y + x 376abe3a6eaShanjiezhou } 377*3959e94dS曾俊 378abe3a6eaShanjiezhou pub fn get_start_index_by_lineid_lineindex(lineid: LineId, lineindex: LineIndex) -> usize { 379abe3a6eaShanjiezhou // x 左上角列像素点位置 380abe3a6eaShanjiezhou // y 左上角行像素点位置 381abe3a6eaShanjiezhou let index_x: u32 = lineindex.into(); 382abe3a6eaShanjiezhou let x: u32 = index_x * TEXTUI_CHAR_WIDTH; 383abe3a6eaShanjiezhou 384abe3a6eaShanjiezhou let id_y: u32 = lineid.into(); 385abe3a6eaShanjiezhou let y: u32 = id_y * TEXTUI_CHAR_HEIGHT; 386abe3a6eaShanjiezhou 387abe3a6eaShanjiezhou TextuiBuf::get_index_by_x_y(x as usize, y as usize) 388abe3a6eaShanjiezhou } 389abe3a6eaShanjiezhou } 390abe3a6eaShanjiezhou 391abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] 392abe3a6eaShanjiezhou pub struct Font([u8; 16]); 393abe3a6eaShanjiezhou impl Font { 394abe3a6eaShanjiezhou #[inline] 395abe3a6eaShanjiezhou pub fn get_font(character: char) -> Font { 396abe3a6eaShanjiezhou let x = FONT_8x16.char_map(character); 397abe3a6eaShanjiezhou 398abe3a6eaShanjiezhou let mut data = [0u8; 16]; 399abe3a6eaShanjiezhou data.copy_from_slice(x); 400abe3a6eaShanjiezhou return Font(data); 401abe3a6eaShanjiezhou } 402abe3a6eaShanjiezhou pub fn is_frcolor(&self, height: usize, width: usize) -> bool { 403abe3a6eaShanjiezhou let w = self.0[height]; 404abe3a6eaShanjiezhou let testbit = 1 << (8 - width); 405abe3a6eaShanjiezhou w & testbit != 0 406abe3a6eaShanjiezhou } 407abe3a6eaShanjiezhou } 408abe3a6eaShanjiezhou 409abe3a6eaShanjiezhou impl TextuiCharChromatic { 410abe3a6eaShanjiezhou pub fn new(c: Option<char>, frcolor: FontColor, bkcolor: FontColor) -> Self { 411abe3a6eaShanjiezhou TextuiCharChromatic { 412abe3a6eaShanjiezhou c, 413abe3a6eaShanjiezhou frcolor, 414abe3a6eaShanjiezhou bkcolor, 415abe3a6eaShanjiezhou } 416abe3a6eaShanjiezhou } 417abe3a6eaShanjiezhou 418abe3a6eaShanjiezhou /// 将该字符对象输出到缓冲区 419abe3a6eaShanjiezhou /// ## 参数 420abe3a6eaShanjiezhou /// -line_id 要放入的真实行号 421abe3a6eaShanjiezhou /// -index 要放入的真实列号 422abe3a6eaShanjiezhou pub fn textui_refresh_character( 423abe3a6eaShanjiezhou &self, 424abe3a6eaShanjiezhou lineid: LineId, 425abe3a6eaShanjiezhou lineindex: LineIndex, 426abe3a6eaShanjiezhou ) -> Result<i32, SystemError> { 427abe3a6eaShanjiezhou // 找到要渲染的字符的像素点数据 428abe3a6eaShanjiezhou 429abe3a6eaShanjiezhou let font: Font = Font::get_font(self.c.unwrap_or(' ')); 430abe3a6eaShanjiezhou 431abe3a6eaShanjiezhou let mut count = TextuiBuf::get_start_index_by_lineid_lineindex(lineid, lineindex); 432abe3a6eaShanjiezhou 4331496ba7bSLoGin let mut _binding = textui_framework().metadata.read().buf_info(); 4341496ba7bSLoGin 4351496ba7bSLoGin let mut buf = TextuiBuf::new(&mut _binding); 4361496ba7bSLoGin 437abe3a6eaShanjiezhou // 在缓冲区画出一个字体,每个字体有TEXTUI_CHAR_HEIGHT行,TEXTUI_CHAR_WIDTH列个像素点 438abe3a6eaShanjiezhou for i in 0..TEXTUI_CHAR_HEIGHT { 439abe3a6eaShanjiezhou let start = count; 440abe3a6eaShanjiezhou for j in 0..TEXTUI_CHAR_WIDTH { 441abe3a6eaShanjiezhou if font.is_frcolor(i as usize, j as usize) { 442abe3a6eaShanjiezhou // 字,显示前景色 443abe3a6eaShanjiezhou buf.put_color_in_pixel(self.frcolor.into(), count); 444abe3a6eaShanjiezhou } else { 445abe3a6eaShanjiezhou // 背景色 446abe3a6eaShanjiezhou buf.put_color_in_pixel(self.bkcolor.into(), count); 447abe3a6eaShanjiezhou } 448abe3a6eaShanjiezhou count += 1; 449abe3a6eaShanjiezhou } 450abe3a6eaShanjiezhou count = TextuiBuf::get_index_of_next_line(start); 451abe3a6eaShanjiezhou } 452abe3a6eaShanjiezhou 453abe3a6eaShanjiezhou return Ok(0); 454abe3a6eaShanjiezhou } 455abe3a6eaShanjiezhou 456abe3a6eaShanjiezhou pub fn no_init_textui_render_chromatic(&self, lineid: LineId, lineindex: LineIndex) { 457abe3a6eaShanjiezhou // 找到要渲染的字符的像素点数据 458abe3a6eaShanjiezhou let font = Font::get_font(self.c.unwrap_or(' ')); 459abe3a6eaShanjiezhou 460abe3a6eaShanjiezhou // x 左上角列像素点位置 461abe3a6eaShanjiezhou // y 左上角行像素点位置 462abe3a6eaShanjiezhou let index_x: u32 = lineindex.into(); 463abe3a6eaShanjiezhou let x: u32 = index_x * TEXTUI_CHAR_WIDTH; 464abe3a6eaShanjiezhou 465abe3a6eaShanjiezhou let id_y: u32 = lineid.into(); 466abe3a6eaShanjiezhou let y: u32 = id_y * TEXTUI_CHAR_HEIGHT; 4672755467cS曾俊 let buf_depth = video_refresh_manager().device_buffer().bit_depth(); 4681496ba7bSLoGin let buf_width = video_refresh_manager().device_buffer().width(); 4692755467cS曾俊 let byte_num_of_depth = (buf_depth / 8) as usize; 4702755467cS曾俊 471abe3a6eaShanjiezhou // 找到输入缓冲区的起始地址位置 4721496ba7bSLoGin let buf_start = 4731496ba7bSLoGin if let ScmBuffer::DeviceBuffer(vaddr) = video_refresh_manager().device_buffer().buf { 4741496ba7bSLoGin vaddr 4751496ba7bSLoGin } else { 4761496ba7bSLoGin panic!("device buffer is not init"); 4771496ba7bSLoGin }; 478abe3a6eaShanjiezhou 479abe3a6eaShanjiezhou let mut testbit: u32; // 用来测试特定行的某列是背景还是字体本身 480abe3a6eaShanjiezhou 481abe3a6eaShanjiezhou // 在缓冲区画出一个字体,每个字体有TEXTUI_CHAR_HEIGHT行,TEXTUI_CHAR_WIDTH列个像素点 482abe3a6eaShanjiezhou for i in 0..TEXTUI_CHAR_HEIGHT { 483abe3a6eaShanjiezhou // 计算出帧缓冲区每一行打印的起始位置的地址(起始位置+(y+i)*缓冲区的宽度+x) 484abe3a6eaShanjiezhou 4852755467cS曾俊 let mut addr: *mut u8 = (buf_start 4862755467cS曾俊 + buf_width as usize * byte_num_of_depth * (y as usize + i as usize) 4872755467cS曾俊 + byte_num_of_depth * x as usize) 4882755467cS曾俊 .data() as *mut u8; 489abe3a6eaShanjiezhou 490abe3a6eaShanjiezhou testbit = 1 << (TEXTUI_CHAR_WIDTH + 1); 491abe3a6eaShanjiezhou 492abe3a6eaShanjiezhou for _j in 0..TEXTUI_CHAR_WIDTH { 4932755467cS曾俊 //该循环是渲染一行像素 494abe3a6eaShanjiezhou //从左往右逐个测试相应位 495abe3a6eaShanjiezhou testbit >>= 1; 496abe3a6eaShanjiezhou if (font.0[i as usize] & testbit as u8) != 0 { 4972755467cS曾俊 let color: u32 = self.frcolor.into(); 4982755467cS曾俊 unsafe { 4992755467cS曾俊 copy_nonoverlapping( 5002755467cS曾俊 &color as *const u32 as *const u8, 5012755467cS曾俊 addr, 5022755467cS曾俊 byte_num_of_depth, 5032755467cS曾俊 ) 5042755467cS曾俊 }; // 字,显示前景色 505abe3a6eaShanjiezhou } else { 5062755467cS曾俊 let color: u32 = self.bkcolor.into(); 5072755467cS曾俊 unsafe { 5082755467cS曾俊 copy_nonoverlapping( 5092755467cS曾俊 &color as *const u32 as *const u8, 5102755467cS曾俊 addr, 5112755467cS曾俊 byte_num_of_depth, 5122755467cS曾俊 ) 5132755467cS曾俊 }; 514abe3a6eaShanjiezhou } 515abe3a6eaShanjiezhou 516abe3a6eaShanjiezhou unsafe { 517b5b571e0SLoGin addr = addr.offset(1); 518abe3a6eaShanjiezhou } 519abe3a6eaShanjiezhou } 520abe3a6eaShanjiezhou } 521abe3a6eaShanjiezhou } 522abe3a6eaShanjiezhou } 523abe3a6eaShanjiezhou 524abe3a6eaShanjiezhou /// 单色显示的虚拟行结构体 525abe3a6eaShanjiezhou 526abe3a6eaShanjiezhou #[derive(Clone, Debug, Default)] 527abe3a6eaShanjiezhou pub struct TextuiVlineNormal { 528abe3a6eaShanjiezhou _characters: Vec<TextuiCharNormal>, // 字符对象数组 529abe3a6eaShanjiezhou _index: i16, // 当前操作的位置 530abe3a6eaShanjiezhou } 531abe3a6eaShanjiezhou /// 彩色显示的虚拟行结构体 532abe3a6eaShanjiezhou 533abe3a6eaShanjiezhou #[derive(Clone, Debug, Default)] 534abe3a6eaShanjiezhou pub struct TextuiVlineChromatic { 535abe3a6eaShanjiezhou chars: Vec<TextuiCharChromatic>, // 字符对象数组 536abe3a6eaShanjiezhou index: LineIndex, // 当前操作的位置 537abe3a6eaShanjiezhou } 538abe3a6eaShanjiezhou impl TextuiVlineChromatic { 539abe3a6eaShanjiezhou pub fn new(char_num: usize) -> Self { 540abe3a6eaShanjiezhou let mut r = TextuiVlineChromatic { 541abe3a6eaShanjiezhou chars: Vec::with_capacity(char_num), 542abe3a6eaShanjiezhou index: LineIndex::new(0), 543abe3a6eaShanjiezhou }; 544abe3a6eaShanjiezhou 545abe3a6eaShanjiezhou for _ in 0..char_num { 546abe3a6eaShanjiezhou r.chars.push(TextuiCharChromatic::new( 547abe3a6eaShanjiezhou None, 548abe3a6eaShanjiezhou FontColor::BLACK, 549abe3a6eaShanjiezhou FontColor::BLACK, 550abe3a6eaShanjiezhou )); 551abe3a6eaShanjiezhou } 552abe3a6eaShanjiezhou 553abe3a6eaShanjiezhou return r; 554abe3a6eaShanjiezhou } 555abe3a6eaShanjiezhou } 556abe3a6eaShanjiezhou 557abe3a6eaShanjiezhou #[derive(Clone, Debug)] 558abe3a6eaShanjiezhou pub enum TextuiVline { 559abe3a6eaShanjiezhou Chromatic(TextuiVlineChromatic), 560abe3a6eaShanjiezhou _Normal(TextuiVlineNormal), 561abe3a6eaShanjiezhou } 562abe3a6eaShanjiezhou 563abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] 564abe3a6eaShanjiezhou pub struct WindowId(u32); 565abe3a6eaShanjiezhou 566abe3a6eaShanjiezhou impl WindowId { 567abe3a6eaShanjiezhou pub fn new() -> Self { 568abe3a6eaShanjiezhou static MAX_ID: AtomicU32 = AtomicU32::new(0); 569abe3a6eaShanjiezhou return WindowId(MAX_ID.fetch_add(1, Ordering::SeqCst)); 570abe3a6eaShanjiezhou } 571abe3a6eaShanjiezhou } 572abe3a6eaShanjiezhou #[allow(dead_code)] 573abe3a6eaShanjiezhou #[derive(Clone, Debug)] 574abe3a6eaShanjiezhou pub struct TextuiWindow { 575abe3a6eaShanjiezhou // 虚拟行是个循环表,头和尾相接 576abe3a6eaShanjiezhou id: WindowId, 577abe3a6eaShanjiezhou // 虚拟行总数 578abe3a6eaShanjiezhou vline_sum: i32, 579abe3a6eaShanjiezhou // 当前已经使用了的虚拟行总数(即在已经输入到缓冲区(之后显示在屏幕上)的虚拟行数量) 580abe3a6eaShanjiezhou vlines_used: i32, 581abe3a6eaShanjiezhou // 位于最顶上的那一个虚拟行的行号 582abe3a6eaShanjiezhou top_vline: LineId, 583abe3a6eaShanjiezhou // 储存虚拟行的数组 584abe3a6eaShanjiezhou vlines: Vec<TextuiVline>, 585abe3a6eaShanjiezhou // 正在操作的vline 586abe3a6eaShanjiezhou vline_operating: LineId, 587abe3a6eaShanjiezhou // 每行最大容纳的字符数 588abe3a6eaShanjiezhou chars_per_line: i32, 589abe3a6eaShanjiezhou // 窗口flag 590abe3a6eaShanjiezhou flags: WindowFlag, 591abe3a6eaShanjiezhou } 592abe3a6eaShanjiezhou 593abe3a6eaShanjiezhou impl TextuiWindow { 594abe3a6eaShanjiezhou /// 使用参数初始化window对象 595abe3a6eaShanjiezhou /// ## 参数 596abe3a6eaShanjiezhou /// 597abe3a6eaShanjiezhou /// -flags 标志位 598abe3a6eaShanjiezhou /// -vlines_num 虚拟行的总数 599abe3a6eaShanjiezhou /// -chars_num 每行最大的字符数 600abe3a6eaShanjiezhou 601abe3a6eaShanjiezhou pub fn new(flags: WindowFlag, vlines_num: i32, chars_num: i32) -> Self { 602abe3a6eaShanjiezhou let mut initial_vlines = Vec::new(); 603abe3a6eaShanjiezhou 604abe3a6eaShanjiezhou for _ in 0..vlines_num { 605abe3a6eaShanjiezhou let vline = TextuiVlineChromatic::new(chars_num as usize); 606abe3a6eaShanjiezhou 607abe3a6eaShanjiezhou initial_vlines.push(TextuiVline::Chromatic(vline)); 608abe3a6eaShanjiezhou } 609abe3a6eaShanjiezhou TextuiWindow { 610abe3a6eaShanjiezhou id: WindowId::new(), 611abe3a6eaShanjiezhou flags, 612abe3a6eaShanjiezhou vline_sum: vlines_num, 613abe3a6eaShanjiezhou vlines_used: 1, 614abe3a6eaShanjiezhou top_vline: LineId::new(0), 615abe3a6eaShanjiezhou vlines: initial_vlines, 616abe3a6eaShanjiezhou vline_operating: LineId::new(0), 617abe3a6eaShanjiezhou chars_per_line: chars_num, 618abe3a6eaShanjiezhou } 619abe3a6eaShanjiezhou } 620abe3a6eaShanjiezhou 621abe3a6eaShanjiezhou /// 刷新某个窗口的缓冲区的某个虚拟行的连续n个字符对象 622abe3a6eaShanjiezhou /// ## 参数 623abe3a6eaShanjiezhou /// - window 窗口结构体 624abe3a6eaShanjiezhou /// - vline_id 要刷新的虚拟行号 625abe3a6eaShanjiezhou /// - start 起始字符号 626abe3a6eaShanjiezhou /// - count 要刷新的字符数量 627abe3a6eaShanjiezhou fn textui_refresh_characters( 628abe3a6eaShanjiezhou &mut self, 629abe3a6eaShanjiezhou vline_id: LineId, 630abe3a6eaShanjiezhou start: LineIndex, 631abe3a6eaShanjiezhou count: i32, 632abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 633abe3a6eaShanjiezhou let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst); 634abe3a6eaShanjiezhou 635abe3a6eaShanjiezhou // 判断虚拟行参数是否合法 636abe3a6eaShanjiezhou if unlikely( 637abe3a6eaShanjiezhou !vline_id.check(self.vline_sum) 638abe3a6eaShanjiezhou || (<LineIndex as Into<i32>>::into(start) + count) > self.chars_per_line, 639abe3a6eaShanjiezhou ) { 640abe3a6eaShanjiezhou return Err(SystemError::EINVAL); 641abe3a6eaShanjiezhou } 642abe3a6eaShanjiezhou // 计算虚拟行对应的真实行(即要渲染的行) 643abe3a6eaShanjiezhou let mut actual_line_id = vline_id - self.top_vline; //为正说明虚拟行不在真实行显示的区域上面 644abe3a6eaShanjiezhou 645abe3a6eaShanjiezhou if <LineId as Into<i32>>::into(actual_line_id) < 0 { 646abe3a6eaShanjiezhou //真实行数小于虚拟行数,则需要加上真实行数的位置,以便正确计算真实行 647abe3a6eaShanjiezhou actual_line_id = actual_line_id + actual_line_sum; 648abe3a6eaShanjiezhou } 649abe3a6eaShanjiezhou 650abe3a6eaShanjiezhou // 将此窗口的某个虚拟行的连续n个字符对象往缓存区写入 651abe3a6eaShanjiezhou if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 652abe3a6eaShanjiezhou let vline = &mut self.vlines[<LineId as Into<usize>>::into(vline_id)]; 653abe3a6eaShanjiezhou let mut i = 0; 654abe3a6eaShanjiezhou let mut index = start; 655abe3a6eaShanjiezhou 656abe3a6eaShanjiezhou while i < count { 657abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = vline { 658abe3a6eaShanjiezhou vline.chars[<LineIndex as Into<usize>>::into(index)] 659abe3a6eaShanjiezhou .textui_refresh_character(actual_line_id, index)?; 660abe3a6eaShanjiezhou 661abe3a6eaShanjiezhou index = index + 1; 662abe3a6eaShanjiezhou } 663abe3a6eaShanjiezhou i += 1; 664abe3a6eaShanjiezhou } 665abe3a6eaShanjiezhou } 666abe3a6eaShanjiezhou 667abe3a6eaShanjiezhou return Ok(()); 668abe3a6eaShanjiezhou } 669abe3a6eaShanjiezhou 670abe3a6eaShanjiezhou /// 重新渲染某个窗口的某个虚拟行 671abe3a6eaShanjiezhou /// ## 参数 672abe3a6eaShanjiezhou 673abe3a6eaShanjiezhou /// - window 窗口结构体 674abe3a6eaShanjiezhou /// - vline_id 虚拟行号 675abe3a6eaShanjiezhou 676abe3a6eaShanjiezhou fn textui_refresh_vline(&mut self, vline_id: LineId) -> Result<(), SystemError> { 677abe3a6eaShanjiezhou if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 678abe3a6eaShanjiezhou return self.textui_refresh_characters( 679abe3a6eaShanjiezhou vline_id, 680abe3a6eaShanjiezhou LineIndex::new(0), 681abe3a6eaShanjiezhou self.chars_per_line, 682abe3a6eaShanjiezhou ); 683abe3a6eaShanjiezhou } else { 684abe3a6eaShanjiezhou //todo支持纯文本字符() 685abe3a6eaShanjiezhou todo!(); 686abe3a6eaShanjiezhou } 687abe3a6eaShanjiezhou } 688abe3a6eaShanjiezhou 689abe3a6eaShanjiezhou // 刷新某个窗口的start 到start + count行(即将这些行输入到缓冲区) 690abe3a6eaShanjiezhou fn textui_refresh_vlines(&mut self, start: LineId, count: i32) -> Result<i32, SystemError> { 691abe3a6eaShanjiezhou let mut refresh_count = count; 692abe3a6eaShanjiezhou for i in <LineId as Into<i32>>::into(start) 693abe3a6eaShanjiezhou ..(self.vline_sum).min(<LineId as Into<i32>>::into(start) + count) 694abe3a6eaShanjiezhou { 695abe3a6eaShanjiezhou self.textui_refresh_vline(LineId::new(i))?; 696abe3a6eaShanjiezhou refresh_count -= 1; 697abe3a6eaShanjiezhou } 698abe3a6eaShanjiezhou //因为虚拟行是循环表 699abe3a6eaShanjiezhou let mut refresh_start = 0; 700abe3a6eaShanjiezhou while refresh_count > 0 { 701abe3a6eaShanjiezhou self.textui_refresh_vline(LineId::new(refresh_start))?; 702abe3a6eaShanjiezhou refresh_start += 1; 703abe3a6eaShanjiezhou refresh_count -= 1; 704abe3a6eaShanjiezhou } 705abe3a6eaShanjiezhou return Ok(0); 706abe3a6eaShanjiezhou } 707abe3a6eaShanjiezhou 708abe3a6eaShanjiezhou /// 往某个窗口的缓冲区的某个虚拟行插入换行 709abe3a6eaShanjiezhou /// ## 参数 710abe3a6eaShanjiezhou /// - window 窗口结构体 711abe3a6eaShanjiezhou /// - vline_id 虚拟行号 712abe3a6eaShanjiezhou fn textui_new_line(&mut self) -> Result<i32, SystemError> { 713abe3a6eaShanjiezhou // todo: 支持在两个虚拟行之间插入一个新行 714abe3a6eaShanjiezhou let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst); 715abe3a6eaShanjiezhou self.vline_operating = self.vline_operating + 1; 716abe3a6eaShanjiezhou //如果已经到了最大行数,则重新从0开始 717abe3a6eaShanjiezhou if !self.vline_operating.check(self.vline_sum) { 718abe3a6eaShanjiezhou self.vline_operating = LineId::new(0); 719abe3a6eaShanjiezhou } 720abe3a6eaShanjiezhou 721abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 722abe3a6eaShanjiezhou &mut (self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]) 723abe3a6eaShanjiezhou { 724abe3a6eaShanjiezhou for i in 0..self.chars_per_line { 725abe3a6eaShanjiezhou if let Some(v_char) = vline.chars.get_mut(i as usize) { 726abe3a6eaShanjiezhou v_char.c = None; 727abe3a6eaShanjiezhou v_char.frcolor = FontColor::BLACK; 728abe3a6eaShanjiezhou v_char.bkcolor = FontColor::BLACK; 729abe3a6eaShanjiezhou } 730abe3a6eaShanjiezhou } 731abe3a6eaShanjiezhou vline.index = LineIndex::new(0); 732abe3a6eaShanjiezhou } 733abe3a6eaShanjiezhou // 当已经使用的虚拟行总数等于真实行总数时,说明窗口中已经显示的文本行数已经达到了窗口的最大容量。这时,如果继续在窗口中添加新的文本,就会导致文本溢出窗口而无法显示。因此,需要往下滚动屏幕来显示更多的文本。 734abe3a6eaShanjiezhou 735abe3a6eaShanjiezhou if self.vlines_used == actual_line_sum { 736abe3a6eaShanjiezhou self.top_vline = self.top_vline + 1; 737abe3a6eaShanjiezhou 738abe3a6eaShanjiezhou if !self.top_vline.check(self.vline_sum) { 739abe3a6eaShanjiezhou self.top_vline = LineId::new(0); 740abe3a6eaShanjiezhou } 741abe3a6eaShanjiezhou 742abe3a6eaShanjiezhou // 刷新所有行 743abe3a6eaShanjiezhou self.textui_refresh_vlines(self.top_vline, actual_line_sum)?; 744abe3a6eaShanjiezhou } else { 745abe3a6eaShanjiezhou //换行说明上一行已经在缓冲区中,所以已经使用的虚拟行总数+1 746abe3a6eaShanjiezhou self.vlines_used += 1; 747abe3a6eaShanjiezhou } 748abe3a6eaShanjiezhou 749abe3a6eaShanjiezhou return Ok(0); 750abe3a6eaShanjiezhou } 751abe3a6eaShanjiezhou 752abe3a6eaShanjiezhou /// 真正向窗口的缓冲区上输入字符的函数(位置为window.vline_operating,window.vline_operating.index) 753abe3a6eaShanjiezhou /// ## 参数 754abe3a6eaShanjiezhou /// - window 755abe3a6eaShanjiezhou /// - character 756abe3a6eaShanjiezhou fn true_textui_putchar_window( 757abe3a6eaShanjiezhou &mut self, 758abe3a6eaShanjiezhou character: char, 759abe3a6eaShanjiezhou frcolor: FontColor, 760abe3a6eaShanjiezhou bkcolor: FontColor, 761abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 762abe3a6eaShanjiezhou // 启用彩色字符 763abe3a6eaShanjiezhou if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 764abe3a6eaShanjiezhou let mut line_index = LineIndex::new(0); //操作的列号 765abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 766abe3a6eaShanjiezhou &mut (self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]) 767abe3a6eaShanjiezhou { 768abe3a6eaShanjiezhou let index = <LineIndex as Into<usize>>::into(vline.index); 769abe3a6eaShanjiezhou 770abe3a6eaShanjiezhou if let Some(v_char) = vline.chars.get_mut(index) { 771abe3a6eaShanjiezhou v_char.c = Some(character); 772abe3a6eaShanjiezhou v_char.frcolor = frcolor; 773abe3a6eaShanjiezhou v_char.bkcolor = bkcolor; 774abe3a6eaShanjiezhou } 775abe3a6eaShanjiezhou line_index = vline.index; 776abe3a6eaShanjiezhou vline.index = vline.index + 1; 777abe3a6eaShanjiezhou } 778abe3a6eaShanjiezhou 779abe3a6eaShanjiezhou self.textui_refresh_characters(self.vline_operating, line_index, 1)?; 780abe3a6eaShanjiezhou 781abe3a6eaShanjiezhou // 加入光标后,因为会识别光标,所以需超过该行最大字符数才能创建新行 782abe3a6eaShanjiezhou if !line_index.check(self.chars_per_line - 1) { 783abe3a6eaShanjiezhou self.textui_new_line()?; 784abe3a6eaShanjiezhou } 785abe3a6eaShanjiezhou } else { 786abe3a6eaShanjiezhou // todo: 支持纯文本字符 787abe3a6eaShanjiezhou todo!(); 788abe3a6eaShanjiezhou } 789abe3a6eaShanjiezhou return Ok(()); 790abe3a6eaShanjiezhou } 791abe3a6eaShanjiezhou /// 根据输入的一个字符在窗口上输出 792abe3a6eaShanjiezhou /// ## 参数 793abe3a6eaShanjiezhou 794abe3a6eaShanjiezhou /// - window 窗口 795abe3a6eaShanjiezhou /// - character 字符 796abe3a6eaShanjiezhou /// - FRcolor 前景色(RGB) 797abe3a6eaShanjiezhou /// - BKcolor 背景色(RGB) 798abe3a6eaShanjiezhou 799abe3a6eaShanjiezhou fn textui_putchar_window( 800abe3a6eaShanjiezhou &mut self, 801abe3a6eaShanjiezhou character: char, 802abe3a6eaShanjiezhou frcolor: FontColor, 803abe3a6eaShanjiezhou bkcolor: FontColor, 804abe3a6eaShanjiezhou is_enable_window: bool, 805abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 806abe3a6eaShanjiezhou let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst); 807abe3a6eaShanjiezhou 808abe3a6eaShanjiezhou //字符'\0'代表ASCII码表中的空字符,表示字符串的结尾 809abe3a6eaShanjiezhou if unlikely(character == '\0') { 810abe3a6eaShanjiezhou return Ok(()); 811abe3a6eaShanjiezhou } 812abe3a6eaShanjiezhou 813abe3a6eaShanjiezhou if unlikely(character == '\r') { 814abe3a6eaShanjiezhou return Ok(()); 815abe3a6eaShanjiezhou } 816abe3a6eaShanjiezhou 817abe3a6eaShanjiezhou // 暂不支持纯文本窗口 818abe3a6eaShanjiezhou if !self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 819abe3a6eaShanjiezhou return Ok(()); 820abe3a6eaShanjiezhou } 821a0c98cd4SJomo send_to_default_serial8250_port(&[character as u8]); 822abe3a6eaShanjiezhou 823abe3a6eaShanjiezhou //进行换行操作 824abe3a6eaShanjiezhou if character == '\n' { 825abe3a6eaShanjiezhou // 换行时还需要输出\r 826a03c4f9dSLoGin send_to_default_serial8250_port(&[b'\r']); 827b5b571e0SLoGin if is_enable_window { 828abe3a6eaShanjiezhou self.textui_new_line()?; 829abe3a6eaShanjiezhou } 830abe3a6eaShanjiezhou return Ok(()); 831abe3a6eaShanjiezhou } 832abe3a6eaShanjiezhou // 输出制表符 833abe3a6eaShanjiezhou else if character == '\t' { 834b5b571e0SLoGin if is_enable_window { 835abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 836abe3a6eaShanjiezhou &self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 837abe3a6eaShanjiezhou { 838abe3a6eaShanjiezhou //打印的空格数(注意将每行分成一个个表格,每个表格为8个字符) 839abe3a6eaShanjiezhou let mut space_to_print = 8 - <LineIndex as Into<usize>>::into(vline.index) % 8; 840abe3a6eaShanjiezhou while space_to_print > 0 { 841abe3a6eaShanjiezhou self.true_textui_putchar_window(' ', frcolor, bkcolor)?; 842abe3a6eaShanjiezhou space_to_print -= 1; 843abe3a6eaShanjiezhou } 844abe3a6eaShanjiezhou } 845abe3a6eaShanjiezhou } 846abe3a6eaShanjiezhou } 847abe3a6eaShanjiezhou // 字符 '\x08' 代表 ASCII 码中的退格字符。它在输出中的作用是将光标向左移动一个位置,并在该位置上输出后续的字符,从而实现字符的删除或替换。 848abe3a6eaShanjiezhou else if character == '\x08' { 849b5b571e0SLoGin if is_enable_window { 850abe3a6eaShanjiezhou let mut tmp = LineIndex(0); 851abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 852abe3a6eaShanjiezhou &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 853abe3a6eaShanjiezhou { 854abe3a6eaShanjiezhou vline.index = vline.index - 1; 855abe3a6eaShanjiezhou tmp = vline.index; 856abe3a6eaShanjiezhou } 857abe3a6eaShanjiezhou if <LineIndex as Into<i32>>::into(tmp) >= 0 { 858abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 859abe3a6eaShanjiezhou &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 860abe3a6eaShanjiezhou { 861abe3a6eaShanjiezhou if let Some(v_char) = 862abe3a6eaShanjiezhou vline.chars.get_mut(<LineIndex as Into<usize>>::into(tmp)) 863abe3a6eaShanjiezhou { 864abe3a6eaShanjiezhou v_char.c = Some(' '); 865abe3a6eaShanjiezhou 866abe3a6eaShanjiezhou v_char.bkcolor = bkcolor; 867abe3a6eaShanjiezhou } 868abe3a6eaShanjiezhou } 869abe3a6eaShanjiezhou return self.textui_refresh_characters(self.vline_operating, tmp, 1); 870abe3a6eaShanjiezhou } 871abe3a6eaShanjiezhou // 需要向上缩一行 872abe3a6eaShanjiezhou if <LineIndex as Into<i32>>::into(tmp) < 0 { 873abe3a6eaShanjiezhou // 当前行为空,需要重新刷新 874abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 875abe3a6eaShanjiezhou &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 876abe3a6eaShanjiezhou { 877abe3a6eaShanjiezhou vline.index = LineIndex::new(0); 878abe3a6eaShanjiezhou for i in 0..self.chars_per_line { 879abe3a6eaShanjiezhou if let Some(v_char) = vline.chars.get_mut(i as usize) { 880abe3a6eaShanjiezhou v_char.c = None; 881abe3a6eaShanjiezhou v_char.frcolor = FontColor::BLACK; 882abe3a6eaShanjiezhou v_char.bkcolor = FontColor::BLACK; 883abe3a6eaShanjiezhou } 884abe3a6eaShanjiezhou } 885abe3a6eaShanjiezhou } 886abe3a6eaShanjiezhou // 上缩一行 887abe3a6eaShanjiezhou self.vline_operating = self.vline_operating - 1; 888abe3a6eaShanjiezhou if self.vline_operating.data() < 0 { 889abe3a6eaShanjiezhou self.vline_operating = LineId(self.vline_sum - 1); 890abe3a6eaShanjiezhou } 891abe3a6eaShanjiezhou 892abe3a6eaShanjiezhou // 考虑是否向上滚动(在top_vline上退格) 893abe3a6eaShanjiezhou if self.vlines_used > actual_line_sum { 894abe3a6eaShanjiezhou self.top_vline = self.top_vline - 1; 895abe3a6eaShanjiezhou if <LineId as Into<i32>>::into(self.top_vline) < 0 { 896abe3a6eaShanjiezhou self.top_vline = LineId(self.vline_sum - 1); 897abe3a6eaShanjiezhou } 898abe3a6eaShanjiezhou } 899abe3a6eaShanjiezhou //因为上缩一行所以显示在屏幕中的虚拟行少一 900abe3a6eaShanjiezhou self.vlines_used -= 1; 901abe3a6eaShanjiezhou self.textui_refresh_vlines(self.top_vline, actual_line_sum)?; 902abe3a6eaShanjiezhou } 903abe3a6eaShanjiezhou } 904b5b571e0SLoGin } else if is_enable_window { 905abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 906abe3a6eaShanjiezhou &self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 907abe3a6eaShanjiezhou { 908abe3a6eaShanjiezhou if !vline.index.check(self.chars_per_line) { 909abe3a6eaShanjiezhou self.textui_new_line()?; 910abe3a6eaShanjiezhou } 911abe3a6eaShanjiezhou 912abe3a6eaShanjiezhou return self.true_textui_putchar_window(character, frcolor, bkcolor); 913abe3a6eaShanjiezhou } 914abe3a6eaShanjiezhou } 915abe3a6eaShanjiezhou 916abe3a6eaShanjiezhou return Ok(()); 917abe3a6eaShanjiezhou } 918abe3a6eaShanjiezhou } 919abe3a6eaShanjiezhou impl Default for TextuiWindow { 920abe3a6eaShanjiezhou fn default() -> Self { 921abe3a6eaShanjiezhou TextuiWindow { 922abe3a6eaShanjiezhou id: WindowId(0), 923abe3a6eaShanjiezhou flags: WindowFlag::TEXTUI_CHROMATIC, 924abe3a6eaShanjiezhou vline_sum: 0, 925abe3a6eaShanjiezhou vlines_used: 1, 926abe3a6eaShanjiezhou top_vline: LineId::new(0), 927abe3a6eaShanjiezhou vlines: Vec::new(), 928abe3a6eaShanjiezhou vline_operating: LineId::new(0), 929abe3a6eaShanjiezhou chars_per_line: 0, 930abe3a6eaShanjiezhou } 931abe3a6eaShanjiezhou } 932abe3a6eaShanjiezhou } 933abe3a6eaShanjiezhou #[allow(dead_code)] 934abe3a6eaShanjiezhou #[derive(Debug)] 935abe3a6eaShanjiezhou pub struct TextUiFramework { 9361496ba7bSLoGin metadata: RwLock<ScmUiFrameworkMetadata>, 937abe3a6eaShanjiezhou window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>>, 938abe3a6eaShanjiezhou actual_line: AtomicI32, // 真实行的数量(textui的帧缓冲区能容纳的内容的行数) 939abe3a6eaShanjiezhou current_window: Arc<SpinLock<TextuiWindow>>, // 当前的主窗口 940abe3a6eaShanjiezhou default_window: Arc<SpinLock<TextuiWindow>>, // 默认print到的窗口 941abe3a6eaShanjiezhou } 942abe3a6eaShanjiezhou 943abe3a6eaShanjiezhou impl TextUiFramework { 944abe3a6eaShanjiezhou pub fn new( 945abe3a6eaShanjiezhou metadata: ScmUiFrameworkMetadata, 946abe3a6eaShanjiezhou window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>>, 947abe3a6eaShanjiezhou current_window: Arc<SpinLock<TextuiWindow>>, 948abe3a6eaShanjiezhou default_window: Arc<SpinLock<TextuiWindow>>, 949abe3a6eaShanjiezhou ) -> Self { 950abe3a6eaShanjiezhou let actual_line = 951b5b571e0SLoGin AtomicI32::new((metadata.buf_info().height() / TEXTUI_CHAR_HEIGHT) as i32); 952abe3a6eaShanjiezhou let inner = TextUiFramework { 9531496ba7bSLoGin metadata: RwLock::new(metadata), 954abe3a6eaShanjiezhou window_list, 955abe3a6eaShanjiezhou actual_line, 956abe3a6eaShanjiezhou current_window, 957abe3a6eaShanjiezhou default_window, 958abe3a6eaShanjiezhou }; 959abe3a6eaShanjiezhou return inner; 960abe3a6eaShanjiezhou } 961abe3a6eaShanjiezhou } 962abe3a6eaShanjiezhou 9631496ba7bSLoGin impl ScmUiFramework for TextUiFramework { 964abe3a6eaShanjiezhou // 安装ui框架的回调函数 965abe3a6eaShanjiezhou fn install(&self) -> Result<i32, SystemError> { 966a03c4f9dSLoGin send_to_default_serial8250_port("\ntextui_install_handler\n\0".as_bytes()); 967abe3a6eaShanjiezhou return Ok(0); 968abe3a6eaShanjiezhou } 969abe3a6eaShanjiezhou // 卸载ui框架的回调函数 970abe3a6eaShanjiezhou fn uninstall(&self) -> Result<i32, SystemError> { 971abe3a6eaShanjiezhou return Ok(0); 972abe3a6eaShanjiezhou } 973abe3a6eaShanjiezhou // 启用ui框架的回调函数 974abe3a6eaShanjiezhou fn enable(&self) -> Result<i32, SystemError> { 9751a72a751SLoGin textui_enable_put_to_window(); 976abe3a6eaShanjiezhou return Ok(0); 977abe3a6eaShanjiezhou } 978abe3a6eaShanjiezhou // 禁用ui框架的回调函数 979abe3a6eaShanjiezhou fn disable(&self) -> Result<i32, SystemError> { 9801a72a751SLoGin textui_disable_put_to_window(); 981abe3a6eaShanjiezhou 982abe3a6eaShanjiezhou return Ok(0); 983abe3a6eaShanjiezhou } 984abe3a6eaShanjiezhou // 改变ui框架的帧缓冲区的回调函数 985abe3a6eaShanjiezhou fn change(&self, buf_info: ScmBufferInfo) -> Result<i32, SystemError> { 9861496ba7bSLoGin let old_buf = textui_framework().metadata.read().buf_info(); 9871496ba7bSLoGin 9881496ba7bSLoGin textui_framework().metadata.write().set_buf_info(buf_info); 9891496ba7bSLoGin 9901496ba7bSLoGin let mut new_buf = textui_framework().metadata.read().buf_info(); 9911496ba7bSLoGin 9921496ba7bSLoGin new_buf.copy_from_nonoverlapping(&old_buf); 9931496ba7bSLoGin kdebug!("textui change buf_info: old: {:?}", old_buf); 9941496ba7bSLoGin kdebug!("textui change buf_info: new: {:?}", new_buf); 9951496ba7bSLoGin 996abe3a6eaShanjiezhou return Ok(0); 997abe3a6eaShanjiezhou } 998abe3a6eaShanjiezhou /// 获取ScmUiFramework的元数据 999abe3a6eaShanjiezhou /// ## 返回值 1000abe3a6eaShanjiezhou /// 1001abe3a6eaShanjiezhou /// -成功:Ok(ScmUiFramework的元数据) 1002abe3a6eaShanjiezhou /// -失败:Err(错误码) 1003abe3a6eaShanjiezhou fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> { 10041496ba7bSLoGin let metadata = self.metadata.read().clone(); 1005abe3a6eaShanjiezhou 1006abe3a6eaShanjiezhou return Ok(metadata); 1007abe3a6eaShanjiezhou } 1008abe3a6eaShanjiezhou } 1009abe3a6eaShanjiezhou 1010abe3a6eaShanjiezhou /// Mapping from characters to glyph indices. 1011abe3a6eaShanjiezhou pub trait GlyphMapping: Sync { 1012abe3a6eaShanjiezhou /// Maps a character to a glyph index. 1013abe3a6eaShanjiezhou /// 1014abe3a6eaShanjiezhou /// If `c` isn't included in the font the index of a suitable replacement glyph is returned. 1015abe3a6eaShanjiezhou fn index(&self, c: char) -> usize; 1016abe3a6eaShanjiezhou } 1017abe3a6eaShanjiezhou 1018abe3a6eaShanjiezhou impl<F> GlyphMapping for F 1019abe3a6eaShanjiezhou where 1020abe3a6eaShanjiezhou F: Sync + Fn(char) -> usize, 1021abe3a6eaShanjiezhou { 1022abe3a6eaShanjiezhou fn index(&self, c: char) -> usize { 1023abe3a6eaShanjiezhou self(c) 1024abe3a6eaShanjiezhou } 1025abe3a6eaShanjiezhou } 1026abe3a6eaShanjiezhou 1027abe3a6eaShanjiezhou /// 在默认窗口上输出一个字符 1028abe3a6eaShanjiezhou /// ## 参数 1029abe3a6eaShanjiezhou /// - character 字符 1030abe3a6eaShanjiezhou /// - FRcolor 前景色(RGB) 1031abe3a6eaShanjiezhou /// - BKcolor 背景色(RGB) 1032abe3a6eaShanjiezhou 1033abe3a6eaShanjiezhou #[no_mangle] 1034abe3a6eaShanjiezhou pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32) -> i32 { 103552da9a59SGnoCiYeH let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst); 103652da9a59SGnoCiYeH if current_vcnum != -1 { 103752da9a59SGnoCiYeH // tty已经初始化了之后才输出到屏幕 103852da9a59SGnoCiYeH let fr = (fr_color & 0x00ff0000) >> 16; 103952da9a59SGnoCiYeH let fg = (fr_color & 0x0000ff00) >> 8; 104052da9a59SGnoCiYeH let fb = fr_color & 0x000000ff; 104152da9a59SGnoCiYeH let br = (bk_color & 0x00ff0000) >> 16; 104252da9a59SGnoCiYeH let bg = (bk_color & 0x0000ff00) >> 8; 104352da9a59SGnoCiYeH let bb = bk_color & 0x000000ff; 104452da9a59SGnoCiYeH let buf = format!( 104552da9a59SGnoCiYeH "\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{}\x1B[0m", 104652da9a59SGnoCiYeH character as char 104752da9a59SGnoCiYeH ); 1048dfe53cf0SGnoCiYeH let port = tty_port(current_vcnum as usize); 1049dfe53cf0SGnoCiYeH let tty = port.port_data().internal_tty(); 1050b5b571e0SLoGin if let Some(tty) = tty { 1051f3b05a97SGnoCiYeH send_to_default_serial8250_port(&[character]); 105252da9a59SGnoCiYeH return tty 1053f3b05a97SGnoCiYeH .write_without_serial(buf.as_bytes(), buf.len()) 105452da9a59SGnoCiYeH .map(|_| 0) 105552da9a59SGnoCiYeH .unwrap_or_else(|e| e.to_posix_errno()); 105652da9a59SGnoCiYeH } 105752da9a59SGnoCiYeH } 1058abe3a6eaShanjiezhou return textui_putchar( 1059abe3a6eaShanjiezhou character as char, 1060abe3a6eaShanjiezhou FontColor::from(fr_color), 1061abe3a6eaShanjiezhou FontColor::from(bk_color), 1062abe3a6eaShanjiezhou ) 1063abe3a6eaShanjiezhou .map(|_| 0) 1064abe3a6eaShanjiezhou .unwrap_or_else(|e| e.to_posix_errno()); 1065abe3a6eaShanjiezhou } 1066abe3a6eaShanjiezhou 1067abe3a6eaShanjiezhou pub fn textui_putchar( 1068abe3a6eaShanjiezhou character: char, 1069abe3a6eaShanjiezhou fr_color: FontColor, 1070abe3a6eaShanjiezhou bk_color: FontColor, 1071abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 1072abe3a6eaShanjiezhou if unsafe { TEXTUI_IS_INIT } { 1073abe3a6eaShanjiezhou return textui_framework() 1074abe3a6eaShanjiezhou .current_window 1075e2841179SLoGin .lock_irqsave() 1076abe3a6eaShanjiezhou .textui_putchar_window( 1077abe3a6eaShanjiezhou character, 1078abe3a6eaShanjiezhou fr_color, 1079abe3a6eaShanjiezhou bk_color, 10801a72a751SLoGin textui_is_enable_put_to_window(), 1081abe3a6eaShanjiezhou ); 1082abe3a6eaShanjiezhou } else { 1083abe3a6eaShanjiezhou //未初始化暴力输出 1084abe3a6eaShanjiezhou return no_init_textui_putchar_window( 1085abe3a6eaShanjiezhou character, 1086abe3a6eaShanjiezhou fr_color, 1087abe3a6eaShanjiezhou bk_color, 10881a72a751SLoGin textui_is_enable_put_to_window(), 1089abe3a6eaShanjiezhou ); 1090abe3a6eaShanjiezhou } 1091abe3a6eaShanjiezhou } 1092abe3a6eaShanjiezhou 1093fbe6becdSLoGin /// 向默认窗口输出一个字符串 1094fbe6becdSLoGin pub fn textui_putstr( 1095fbe6becdSLoGin string: &str, 1096fbe6becdSLoGin fr_color: FontColor, 1097fbe6becdSLoGin bk_color: FontColor, 1098fbe6becdSLoGin ) -> Result<(), SystemError> { 1099fbe6becdSLoGin let window = if unsafe { TEXTUI_IS_INIT } { 1100fbe6becdSLoGin let fw = textui_framework(); 1101fbe6becdSLoGin let w = fw.current_window.clone(); 1102fbe6becdSLoGin Some(w) 1103fbe6becdSLoGin } else { 1104fbe6becdSLoGin None 1105fbe6becdSLoGin }; 1106fbe6becdSLoGin 1107e2841179SLoGin let mut guard = window.as_ref().map(|w| w.lock_irqsave()); 1108fbe6becdSLoGin 1109fbe6becdSLoGin for character in string.chars() { 1110fbe6becdSLoGin if unsafe { TEXTUI_IS_INIT } { 1111fbe6becdSLoGin guard.as_mut().unwrap().textui_putchar_window( 1112fbe6becdSLoGin character, 1113fbe6becdSLoGin fr_color, 1114fbe6becdSLoGin bk_color, 11151a72a751SLoGin textui_is_enable_put_to_window(), 1116fbe6becdSLoGin )?; 1117fbe6becdSLoGin } else { 1118fbe6becdSLoGin no_init_textui_putchar_window( 1119fbe6becdSLoGin character, 1120fbe6becdSLoGin fr_color, 1121fbe6becdSLoGin bk_color, 11221a72a751SLoGin textui_is_enable_put_to_window(), 1123fbe6becdSLoGin )?; 1124fbe6becdSLoGin } 1125fbe6becdSLoGin } 1126fbe6becdSLoGin 1127fbe6becdSLoGin return Ok(()); 1128fbe6becdSLoGin } 1129fbe6becdSLoGin 1130abe3a6eaShanjiezhou /// 初始化text ui框架 11315b59005fSLoGin #[inline(never)] 11325b59005fSLoGin pub fn textui_init() -> Result<i32, SystemError> { 1133338f6903SLoGin #[cfg(target_arch = "x86_64")] 11345b59005fSLoGin textui_framwork_init(); 1135abe3a6eaShanjiezhou 1136abe3a6eaShanjiezhou return Ok(0); 1137abe3a6eaShanjiezhou } 1138