1*abe3a6eaShanjiezhou use crate::{ 2*abe3a6eaShanjiezhou driver::uart::uart::{c_uart_send, c_uart_send_str, UartPort}, 3*abe3a6eaShanjiezhou include::bindings::bindings::video_frame_buffer_info, 4*abe3a6eaShanjiezhou kinfo, 5*abe3a6eaShanjiezhou libs::{lib_ui::font::FONT_8x16, spinlock::SpinLock}, 6*abe3a6eaShanjiezhou syscall::SystemError, 7*abe3a6eaShanjiezhou }; 8*abe3a6eaShanjiezhou use alloc::{boxed::Box, collections::LinkedList, string::ToString}; 9*abe3a6eaShanjiezhou use alloc::{sync::Arc, vec::Vec}; 10*abe3a6eaShanjiezhou use core::{ 11*abe3a6eaShanjiezhou fmt::Debug, 12*abe3a6eaShanjiezhou intrinsics::unlikely, 13*abe3a6eaShanjiezhou ops::{Add, AddAssign, Sub}, 14*abe3a6eaShanjiezhou sync::atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering}, 15*abe3a6eaShanjiezhou }; 16*abe3a6eaShanjiezhou 17*abe3a6eaShanjiezhou use super::{ 18*abe3a6eaShanjiezhou screen_manager::{ 19*abe3a6eaShanjiezhou scm_register, ScmBufferInfo, ScmFramworkType, ScmUiFramework, ScmUiFrameworkMetadata, 20*abe3a6eaShanjiezhou }, 21*abe3a6eaShanjiezhou textui_no_alloc::no_init_textui_putchar_window, 22*abe3a6eaShanjiezhou }; 23*abe3a6eaShanjiezhou 24*abe3a6eaShanjiezhou /// 声明全局的TEXTUI_FRAMEWORK 25*abe3a6eaShanjiezhou static mut __TEXTUI_FRAMEWORK: Option<Box<TextUiFramework>> = None; 26*abe3a6eaShanjiezhou 27*abe3a6eaShanjiezhou /// 每个字符的宽度和高度(像素) 28*abe3a6eaShanjiezhou pub const TEXTUI_CHAR_WIDTH: u32 = 8; 29*abe3a6eaShanjiezhou 30*abe3a6eaShanjiezhou pub const TEXTUI_CHAR_HEIGHT: u32 = 16; 31*abe3a6eaShanjiezhou 32*abe3a6eaShanjiezhou pub static mut TEXTUI_IS_INIT: bool = false; 33*abe3a6eaShanjiezhou 34*abe3a6eaShanjiezhou pub static ENABLE_PUT_TO_WINDOW: AtomicBool = AtomicBool::new(true); 35*abe3a6eaShanjiezhou 36*abe3a6eaShanjiezhou /// 获取TEXTUI_FRAMEWORK的可变实例 37*abe3a6eaShanjiezhou pub fn textui_framework() -> &'static mut TextUiFramework { 38*abe3a6eaShanjiezhou return unsafe { __TEXTUI_FRAMEWORK.as_mut().unwrap() }; 39*abe3a6eaShanjiezhou } 40*abe3a6eaShanjiezhou /// 初始化TEXTUI_FRAMEWORK 41*abe3a6eaShanjiezhou pub unsafe fn textui_framwork_init() { 42*abe3a6eaShanjiezhou if __TEXTUI_FRAMEWORK.is_none() { 43*abe3a6eaShanjiezhou kinfo!("textuiframework init"); 44*abe3a6eaShanjiezhou let metadata = ScmUiFrameworkMetadata::new("TextUI".to_string(), ScmFramworkType::Text); 45*abe3a6eaShanjiezhou // 为textui框架生成第一个窗口 46*abe3a6eaShanjiezhou let vlines_num = (metadata.buf_info().buf_height() / TEXTUI_CHAR_HEIGHT) as usize; 47*abe3a6eaShanjiezhou 48*abe3a6eaShanjiezhou let chars_num = (metadata.buf_info().buf_width() / TEXTUI_CHAR_WIDTH) as usize; 49*abe3a6eaShanjiezhou 50*abe3a6eaShanjiezhou let initial_window = TextuiWindow::new( 51*abe3a6eaShanjiezhou WindowFlag::TEXTUI_CHROMATIC, 52*abe3a6eaShanjiezhou vlines_num as i32, 53*abe3a6eaShanjiezhou chars_num as i32, 54*abe3a6eaShanjiezhou ); 55*abe3a6eaShanjiezhou 56*abe3a6eaShanjiezhou let current_window: Arc<SpinLock<TextuiWindow>> = Arc::new(SpinLock::new(initial_window)); 57*abe3a6eaShanjiezhou 58*abe3a6eaShanjiezhou let default_window = current_window.clone(); 59*abe3a6eaShanjiezhou 60*abe3a6eaShanjiezhou // 生成窗口链表,并把上面窗口添加进textui框架的窗口链表中 61*abe3a6eaShanjiezhou let window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>> = 62*abe3a6eaShanjiezhou Arc::new(SpinLock::new(LinkedList::new())); 63*abe3a6eaShanjiezhou window_list.lock().push_back(current_window.clone()); 64*abe3a6eaShanjiezhou 65*abe3a6eaShanjiezhou __TEXTUI_FRAMEWORK = Some(Box::new(TextUiFramework::new( 66*abe3a6eaShanjiezhou metadata, 67*abe3a6eaShanjiezhou window_list, 68*abe3a6eaShanjiezhou current_window, 69*abe3a6eaShanjiezhou default_window, 70*abe3a6eaShanjiezhou ))); 71*abe3a6eaShanjiezhou } else { 72*abe3a6eaShanjiezhou panic!("Try to init TEXTUI_FRAMEWORK twice!"); 73*abe3a6eaShanjiezhou } 74*abe3a6eaShanjiezhou } 75*abe3a6eaShanjiezhou // window标志位 76*abe3a6eaShanjiezhou bitflags! { 77*abe3a6eaShanjiezhou pub struct WindowFlag: u8 { 78*abe3a6eaShanjiezhou // 采用彩色字符 79*abe3a6eaShanjiezhou const TEXTUI_CHROMATIC = 1 << 0; 80*abe3a6eaShanjiezhou } 81*abe3a6eaShanjiezhou } 82*abe3a6eaShanjiezhou 83*abe3a6eaShanjiezhou /** 84*abe3a6eaShanjiezhou * @brief 黑白字符对象 85*abe3a6eaShanjiezhou * 86*abe3a6eaShanjiezhou */ 87*abe3a6eaShanjiezhou #[derive(Clone, Debug)] 88*abe3a6eaShanjiezhou struct TextuiCharNormal { 89*abe3a6eaShanjiezhou _data: u8, 90*abe3a6eaShanjiezhou } 91*abe3a6eaShanjiezhou 92*abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)] 93*abe3a6eaShanjiezhou pub struct LineId(i32); 94*abe3a6eaShanjiezhou impl LineId { 95*abe3a6eaShanjiezhou pub fn new(num: i32) -> Self { 96*abe3a6eaShanjiezhou LineId(num) 97*abe3a6eaShanjiezhou } 98*abe3a6eaShanjiezhou 99*abe3a6eaShanjiezhou pub fn check(&self, max: i32) -> bool { 100*abe3a6eaShanjiezhou self.0 < max && self.0 >= 0 101*abe3a6eaShanjiezhou } 102*abe3a6eaShanjiezhou 103*abe3a6eaShanjiezhou pub fn data(&self) -> i32 { 104*abe3a6eaShanjiezhou self.0 105*abe3a6eaShanjiezhou } 106*abe3a6eaShanjiezhou } 107*abe3a6eaShanjiezhou impl Add<i32> for LineId { 108*abe3a6eaShanjiezhou type Output = LineId; 109*abe3a6eaShanjiezhou fn add(self, rhs: i32) -> Self::Output { 110*abe3a6eaShanjiezhou LineId::new(self.0 + rhs) 111*abe3a6eaShanjiezhou } 112*abe3a6eaShanjiezhou } 113*abe3a6eaShanjiezhou impl Sub<i32> for LineId { 114*abe3a6eaShanjiezhou type Output = LineId; 115*abe3a6eaShanjiezhou 116*abe3a6eaShanjiezhou fn sub(self, rhs: i32) -> Self::Output { 117*abe3a6eaShanjiezhou LineId::new(self.0 - rhs) 118*abe3a6eaShanjiezhou } 119*abe3a6eaShanjiezhou } 120*abe3a6eaShanjiezhou 121*abe3a6eaShanjiezhou impl Into<i32> for LineId { 122*abe3a6eaShanjiezhou fn into(self) -> i32 { 123*abe3a6eaShanjiezhou self.0.clone() 124*abe3a6eaShanjiezhou } 125*abe3a6eaShanjiezhou } 126*abe3a6eaShanjiezhou impl Into<u32> for LineId { 127*abe3a6eaShanjiezhou fn into(self) -> u32 { 128*abe3a6eaShanjiezhou self.0.clone() as u32 129*abe3a6eaShanjiezhou } 130*abe3a6eaShanjiezhou } 131*abe3a6eaShanjiezhou impl Into<usize> for LineId { 132*abe3a6eaShanjiezhou fn into(self) -> usize { 133*abe3a6eaShanjiezhou self.0.clone() as usize 134*abe3a6eaShanjiezhou } 135*abe3a6eaShanjiezhou } 136*abe3a6eaShanjiezhou impl Sub<LineId> for LineId { 137*abe3a6eaShanjiezhou type Output = LineId; 138*abe3a6eaShanjiezhou 139*abe3a6eaShanjiezhou fn sub(mut self, rhs: LineId) -> Self::Output { 140*abe3a6eaShanjiezhou self.0 -= rhs.0; 141*abe3a6eaShanjiezhou return self; 142*abe3a6eaShanjiezhou } 143*abe3a6eaShanjiezhou } 144*abe3a6eaShanjiezhou impl AddAssign<LineId> for LineId { 145*abe3a6eaShanjiezhou fn add_assign(&mut self, rhs: LineId) { 146*abe3a6eaShanjiezhou self.0 += rhs.0; 147*abe3a6eaShanjiezhou } 148*abe3a6eaShanjiezhou } 149*abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)] 150*abe3a6eaShanjiezhou pub struct LineIndex(i32); 151*abe3a6eaShanjiezhou impl LineIndex { 152*abe3a6eaShanjiezhou pub fn new(num: i32) -> Self { 153*abe3a6eaShanjiezhou LineIndex(num) 154*abe3a6eaShanjiezhou } 155*abe3a6eaShanjiezhou pub fn check(&self, chars_per_line: i32) -> bool { 156*abe3a6eaShanjiezhou self.0 < chars_per_line && self.0 >= 0 157*abe3a6eaShanjiezhou } 158*abe3a6eaShanjiezhou } 159*abe3a6eaShanjiezhou impl Add<LineIndex> for LineIndex { 160*abe3a6eaShanjiezhou type Output = LineIndex; 161*abe3a6eaShanjiezhou 162*abe3a6eaShanjiezhou fn add(self, rhs: LineIndex) -> Self::Output { 163*abe3a6eaShanjiezhou LineIndex::new(self.0 + rhs.0) 164*abe3a6eaShanjiezhou } 165*abe3a6eaShanjiezhou } 166*abe3a6eaShanjiezhou impl Add<i32> for LineIndex { 167*abe3a6eaShanjiezhou // type Output = Self; 168*abe3a6eaShanjiezhou type Output = LineIndex; 169*abe3a6eaShanjiezhou 170*abe3a6eaShanjiezhou fn add(self, rhs: i32) -> Self::Output { 171*abe3a6eaShanjiezhou LineIndex::new(self.0 + rhs) 172*abe3a6eaShanjiezhou } 173*abe3a6eaShanjiezhou } 174*abe3a6eaShanjiezhou impl Sub<i32> for LineIndex { 175*abe3a6eaShanjiezhou type Output = LineIndex; 176*abe3a6eaShanjiezhou 177*abe3a6eaShanjiezhou fn sub(self, rhs: i32) -> Self::Output { 178*abe3a6eaShanjiezhou LineIndex::new(self.0 - rhs) 179*abe3a6eaShanjiezhou } 180*abe3a6eaShanjiezhou } 181*abe3a6eaShanjiezhou 182*abe3a6eaShanjiezhou impl Into<i32> for LineIndex { 183*abe3a6eaShanjiezhou fn into(self) -> i32 { 184*abe3a6eaShanjiezhou self.0.clone() 185*abe3a6eaShanjiezhou } 186*abe3a6eaShanjiezhou } 187*abe3a6eaShanjiezhou impl Into<u32> for LineIndex { 188*abe3a6eaShanjiezhou fn into(self) -> u32 { 189*abe3a6eaShanjiezhou self.0.clone() as u32 190*abe3a6eaShanjiezhou } 191*abe3a6eaShanjiezhou } 192*abe3a6eaShanjiezhou impl Into<usize> for LineIndex { 193*abe3a6eaShanjiezhou fn into(self) -> usize { 194*abe3a6eaShanjiezhou self.0.clone() as usize 195*abe3a6eaShanjiezhou } 196*abe3a6eaShanjiezhou } 197*abe3a6eaShanjiezhou #[derive(Copy, Clone, Debug)] 198*abe3a6eaShanjiezhou pub struct FontColor(u32); 199*abe3a6eaShanjiezhou #[allow(dead_code)] 200*abe3a6eaShanjiezhou impl FontColor { 201*abe3a6eaShanjiezhou pub const BLUE: FontColor = FontColor::new(0, 0, 0xff); 202*abe3a6eaShanjiezhou pub const RED: FontColor = FontColor::new(0xff, 0, 0); 203*abe3a6eaShanjiezhou pub const GREEN: FontColor = FontColor::new(0, 0xff, 0); 204*abe3a6eaShanjiezhou pub const WHITE: FontColor = FontColor::new(0xff, 0xff, 0xff); 205*abe3a6eaShanjiezhou pub const BLACK: FontColor = FontColor::new(0, 0, 0); 206*abe3a6eaShanjiezhou pub const YELLOW: FontColor = FontColor::new(0xff, 0xff, 0); 207*abe3a6eaShanjiezhou pub const ORANGE: FontColor = FontColor::new(0xff, 0x80, 0); 208*abe3a6eaShanjiezhou pub const INDIGO: FontColor = FontColor::new(0x00, 0xff, 0xff); 209*abe3a6eaShanjiezhou pub const PURPLE: FontColor = FontColor::new(0x80, 0x00, 0xff); 210*abe3a6eaShanjiezhou 211*abe3a6eaShanjiezhou pub const fn new(r: u8, g: u8, b: u8) -> Self { 212*abe3a6eaShanjiezhou let val = ((r as u32) << 16) | ((g as u32) << 8) | (b as u32); 213*abe3a6eaShanjiezhou return FontColor(val & 0x00ffffff); 214*abe3a6eaShanjiezhou } 215*abe3a6eaShanjiezhou } 216*abe3a6eaShanjiezhou 217*abe3a6eaShanjiezhou impl From<u32> for FontColor { 218*abe3a6eaShanjiezhou fn from(value: u32) -> Self { 219*abe3a6eaShanjiezhou return Self(value & 0x00ffffff); 220*abe3a6eaShanjiezhou } 221*abe3a6eaShanjiezhou } 222*abe3a6eaShanjiezhou impl Into<usize> for FontColor { 223*abe3a6eaShanjiezhou fn into(self) -> usize { 224*abe3a6eaShanjiezhou self.0.clone() as usize 225*abe3a6eaShanjiezhou } 226*abe3a6eaShanjiezhou } 227*abe3a6eaShanjiezhou impl Into<u32> for FontColor { 228*abe3a6eaShanjiezhou fn into(self) -> u32 { 229*abe3a6eaShanjiezhou self.0.clone() 230*abe3a6eaShanjiezhou } 231*abe3a6eaShanjiezhou } 232*abe3a6eaShanjiezhou impl Into<u16> for FontColor { 233*abe3a6eaShanjiezhou fn into(self) -> u16 { 234*abe3a6eaShanjiezhou self.0.clone() as u16 235*abe3a6eaShanjiezhou } 236*abe3a6eaShanjiezhou } 237*abe3a6eaShanjiezhou impl Into<u64> for FontColor { 238*abe3a6eaShanjiezhou fn into(self) -> u64 { 239*abe3a6eaShanjiezhou self.0.clone() as u64 240*abe3a6eaShanjiezhou } 241*abe3a6eaShanjiezhou } 242*abe3a6eaShanjiezhou 243*abe3a6eaShanjiezhou /// 彩色字符对象 244*abe3a6eaShanjiezhou 245*abe3a6eaShanjiezhou #[derive(Clone, Debug, Copy)] 246*abe3a6eaShanjiezhou pub struct TextuiCharChromatic { 247*abe3a6eaShanjiezhou c: Option<char>, 248*abe3a6eaShanjiezhou 249*abe3a6eaShanjiezhou // 前景色 250*abe3a6eaShanjiezhou frcolor: FontColor, // rgb 251*abe3a6eaShanjiezhou 252*abe3a6eaShanjiezhou // 背景色 253*abe3a6eaShanjiezhou bkcolor: FontColor, // rgb 254*abe3a6eaShanjiezhou } 255*abe3a6eaShanjiezhou 256*abe3a6eaShanjiezhou #[derive(Debug)] 257*abe3a6eaShanjiezhou pub struct TextuiBuf<'a>(&'a mut [u32]); 258*abe3a6eaShanjiezhou 259*abe3a6eaShanjiezhou impl TextuiBuf<'_> { 260*abe3a6eaShanjiezhou pub fn new(buf: &mut [u32]) -> TextuiBuf { 261*abe3a6eaShanjiezhou TextuiBuf(buf) 262*abe3a6eaShanjiezhou } 263*abe3a6eaShanjiezhou pub fn put_color_in_pixel(&mut self, color: u32, index: usize) { 264*abe3a6eaShanjiezhou let buf: &mut [u32] = self.0; 265*abe3a6eaShanjiezhou buf[index] = color; 266*abe3a6eaShanjiezhou } 267*abe3a6eaShanjiezhou pub fn get_index_of_next_line(now_index: usize) -> usize { 268*abe3a6eaShanjiezhou textui_framework().metadata.buf_info().buf_width() as usize + now_index 269*abe3a6eaShanjiezhou } 270*abe3a6eaShanjiezhou pub fn get_index_by_x_y(x: usize, y: usize) -> usize { 271*abe3a6eaShanjiezhou textui_framework().metadata.buf_info().buf_width() as usize * y + x 272*abe3a6eaShanjiezhou } 273*abe3a6eaShanjiezhou pub fn get_start_index_by_lineid_lineindex(lineid: LineId, lineindex: LineIndex) -> usize { 274*abe3a6eaShanjiezhou // x 左上角列像素点位置 275*abe3a6eaShanjiezhou // y 左上角行像素点位置 276*abe3a6eaShanjiezhou let index_x: u32 = lineindex.into(); 277*abe3a6eaShanjiezhou let x: u32 = index_x * TEXTUI_CHAR_WIDTH; 278*abe3a6eaShanjiezhou 279*abe3a6eaShanjiezhou let id_y: u32 = lineid.into(); 280*abe3a6eaShanjiezhou let y: u32 = id_y * TEXTUI_CHAR_HEIGHT; 281*abe3a6eaShanjiezhou 282*abe3a6eaShanjiezhou TextuiBuf::get_index_by_x_y(x as usize, y as usize) 283*abe3a6eaShanjiezhou } 284*abe3a6eaShanjiezhou } 285*abe3a6eaShanjiezhou 286*abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] 287*abe3a6eaShanjiezhou pub struct Font([u8; 16]); 288*abe3a6eaShanjiezhou impl Font { 289*abe3a6eaShanjiezhou #[inline] 290*abe3a6eaShanjiezhou pub fn get_font(character: char) -> Font { 291*abe3a6eaShanjiezhou let x = FONT_8x16.char_map(character); 292*abe3a6eaShanjiezhou 293*abe3a6eaShanjiezhou let mut data = [0u8; 16]; 294*abe3a6eaShanjiezhou data.copy_from_slice(x); 295*abe3a6eaShanjiezhou return Font(data); 296*abe3a6eaShanjiezhou } 297*abe3a6eaShanjiezhou pub fn is_frcolor(&self, height: usize, width: usize) -> bool { 298*abe3a6eaShanjiezhou let w = self.0[height]; 299*abe3a6eaShanjiezhou let testbit = 1 << (8 - width); 300*abe3a6eaShanjiezhou w & testbit != 0 301*abe3a6eaShanjiezhou } 302*abe3a6eaShanjiezhou } 303*abe3a6eaShanjiezhou 304*abe3a6eaShanjiezhou impl TextuiCharChromatic { 305*abe3a6eaShanjiezhou pub fn new(c: Option<char>, frcolor: FontColor, bkcolor: FontColor) -> Self { 306*abe3a6eaShanjiezhou TextuiCharChromatic { 307*abe3a6eaShanjiezhou c, 308*abe3a6eaShanjiezhou frcolor, 309*abe3a6eaShanjiezhou bkcolor, 310*abe3a6eaShanjiezhou } 311*abe3a6eaShanjiezhou } 312*abe3a6eaShanjiezhou 313*abe3a6eaShanjiezhou /// 将该字符对象输出到缓冲区 314*abe3a6eaShanjiezhou /// ## 参数 315*abe3a6eaShanjiezhou /// -line_id 要放入的真实行号 316*abe3a6eaShanjiezhou /// -index 要放入的真实列号 317*abe3a6eaShanjiezhou pub fn textui_refresh_character( 318*abe3a6eaShanjiezhou &self, 319*abe3a6eaShanjiezhou lineid: LineId, 320*abe3a6eaShanjiezhou lineindex: LineIndex, 321*abe3a6eaShanjiezhou ) -> Result<i32, SystemError> { 322*abe3a6eaShanjiezhou // 找到要渲染的字符的像素点数据 323*abe3a6eaShanjiezhou 324*abe3a6eaShanjiezhou let font: Font = Font::get_font(self.c.unwrap_or(' ')); 325*abe3a6eaShanjiezhou 326*abe3a6eaShanjiezhou let mut count = TextuiBuf::get_start_index_by_lineid_lineindex(lineid, lineindex); 327*abe3a6eaShanjiezhou 328*abe3a6eaShanjiezhou let mut buf = TextuiBuf::new(textui_framework().metadata.buf()); 329*abe3a6eaShanjiezhou // 在缓冲区画出一个字体,每个字体有TEXTUI_CHAR_HEIGHT行,TEXTUI_CHAR_WIDTH列个像素点 330*abe3a6eaShanjiezhou for i in 0..TEXTUI_CHAR_HEIGHT { 331*abe3a6eaShanjiezhou let start = count; 332*abe3a6eaShanjiezhou for j in 0..TEXTUI_CHAR_WIDTH { 333*abe3a6eaShanjiezhou if font.is_frcolor(i as usize, j as usize) { 334*abe3a6eaShanjiezhou // 字,显示前景色 335*abe3a6eaShanjiezhou buf.put_color_in_pixel(self.frcolor.into(), count); 336*abe3a6eaShanjiezhou } else { 337*abe3a6eaShanjiezhou // 背景色 338*abe3a6eaShanjiezhou buf.put_color_in_pixel(self.bkcolor.into(), count); 339*abe3a6eaShanjiezhou } 340*abe3a6eaShanjiezhou count += 1; 341*abe3a6eaShanjiezhou } 342*abe3a6eaShanjiezhou count = TextuiBuf::get_index_of_next_line(start); 343*abe3a6eaShanjiezhou } 344*abe3a6eaShanjiezhou 345*abe3a6eaShanjiezhou return Ok(0); 346*abe3a6eaShanjiezhou } 347*abe3a6eaShanjiezhou 348*abe3a6eaShanjiezhou pub fn no_init_textui_render_chromatic(&self, lineid: LineId, lineindex: LineIndex) { 349*abe3a6eaShanjiezhou // 找到要渲染的字符的像素点数据 350*abe3a6eaShanjiezhou let font = Font::get_font(self.c.unwrap_or(' ')); 351*abe3a6eaShanjiezhou 352*abe3a6eaShanjiezhou // x 左上角列像素点位置 353*abe3a6eaShanjiezhou // y 左上角行像素点位置 354*abe3a6eaShanjiezhou let index_x: u32 = lineindex.into(); 355*abe3a6eaShanjiezhou let x: u32 = index_x * TEXTUI_CHAR_WIDTH; 356*abe3a6eaShanjiezhou 357*abe3a6eaShanjiezhou let id_y: u32 = lineid.into(); 358*abe3a6eaShanjiezhou let y: u32 = id_y * TEXTUI_CHAR_HEIGHT; 359*abe3a6eaShanjiezhou // 找到输入缓冲区的起始地址位置 360*abe3a6eaShanjiezhou let fb = unsafe { video_frame_buffer_info.vaddr }; 361*abe3a6eaShanjiezhou 362*abe3a6eaShanjiezhou let mut testbit: u32; // 用来测试特定行的某列是背景还是字体本身 363*abe3a6eaShanjiezhou 364*abe3a6eaShanjiezhou // 在缓冲区画出一个字体,每个字体有TEXTUI_CHAR_HEIGHT行,TEXTUI_CHAR_WIDTH列个像素点 365*abe3a6eaShanjiezhou for i in 0..TEXTUI_CHAR_HEIGHT { 366*abe3a6eaShanjiezhou // 计算出帧缓冲区每一行打印的起始位置的地址(起始位置+(y+i)*缓冲区的宽度+x) 367*abe3a6eaShanjiezhou 368*abe3a6eaShanjiezhou let mut addr: *mut u32 = (fb 369*abe3a6eaShanjiezhou + unsafe { video_frame_buffer_info.width } as u64 * 4 * (y as u64 + i as u64) 370*abe3a6eaShanjiezhou + 4 * x as u64) as *mut u32; 371*abe3a6eaShanjiezhou 372*abe3a6eaShanjiezhou testbit = 1 << (TEXTUI_CHAR_WIDTH + 1); 373*abe3a6eaShanjiezhou 374*abe3a6eaShanjiezhou for _j in 0..TEXTUI_CHAR_WIDTH { 375*abe3a6eaShanjiezhou //从左往右逐个测试相应位 376*abe3a6eaShanjiezhou testbit >>= 1; 377*abe3a6eaShanjiezhou if (font.0[i as usize] & testbit as u8) != 0 { 378*abe3a6eaShanjiezhou unsafe { *addr = self.frcolor.into() }; // 字,显示前景色 379*abe3a6eaShanjiezhou } else { 380*abe3a6eaShanjiezhou unsafe { *addr = self.bkcolor.into() }; // 背景色 381*abe3a6eaShanjiezhou } 382*abe3a6eaShanjiezhou 383*abe3a6eaShanjiezhou unsafe { 384*abe3a6eaShanjiezhou addr = (addr.offset(1)) as *mut u32; 385*abe3a6eaShanjiezhou } 386*abe3a6eaShanjiezhou } 387*abe3a6eaShanjiezhou } 388*abe3a6eaShanjiezhou } 389*abe3a6eaShanjiezhou } 390*abe3a6eaShanjiezhou 391*abe3a6eaShanjiezhou /// 单色显示的虚拟行结构体 392*abe3a6eaShanjiezhou 393*abe3a6eaShanjiezhou #[derive(Clone, Debug, Default)] 394*abe3a6eaShanjiezhou pub struct TextuiVlineNormal { 395*abe3a6eaShanjiezhou _characters: Vec<TextuiCharNormal>, // 字符对象数组 396*abe3a6eaShanjiezhou _index: i16, // 当前操作的位置 397*abe3a6eaShanjiezhou } 398*abe3a6eaShanjiezhou /// 彩色显示的虚拟行结构体 399*abe3a6eaShanjiezhou 400*abe3a6eaShanjiezhou #[derive(Clone, Debug, Default)] 401*abe3a6eaShanjiezhou pub struct TextuiVlineChromatic { 402*abe3a6eaShanjiezhou chars: Vec<TextuiCharChromatic>, // 字符对象数组 403*abe3a6eaShanjiezhou index: LineIndex, // 当前操作的位置 404*abe3a6eaShanjiezhou } 405*abe3a6eaShanjiezhou impl TextuiVlineChromatic { 406*abe3a6eaShanjiezhou pub fn new(char_num: usize) -> Self { 407*abe3a6eaShanjiezhou let mut r = TextuiVlineChromatic { 408*abe3a6eaShanjiezhou chars: Vec::with_capacity(char_num), 409*abe3a6eaShanjiezhou index: LineIndex::new(0), 410*abe3a6eaShanjiezhou }; 411*abe3a6eaShanjiezhou 412*abe3a6eaShanjiezhou for _ in 0..char_num { 413*abe3a6eaShanjiezhou r.chars.push(TextuiCharChromatic::new( 414*abe3a6eaShanjiezhou None, 415*abe3a6eaShanjiezhou FontColor::BLACK, 416*abe3a6eaShanjiezhou FontColor::BLACK, 417*abe3a6eaShanjiezhou )); 418*abe3a6eaShanjiezhou } 419*abe3a6eaShanjiezhou 420*abe3a6eaShanjiezhou return r; 421*abe3a6eaShanjiezhou } 422*abe3a6eaShanjiezhou } 423*abe3a6eaShanjiezhou 424*abe3a6eaShanjiezhou #[derive(Clone, Debug)] 425*abe3a6eaShanjiezhou pub enum TextuiVline { 426*abe3a6eaShanjiezhou Chromatic(TextuiVlineChromatic), 427*abe3a6eaShanjiezhou _Normal(TextuiVlineNormal), 428*abe3a6eaShanjiezhou } 429*abe3a6eaShanjiezhou 430*abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)] 431*abe3a6eaShanjiezhou pub struct WindowId(u32); 432*abe3a6eaShanjiezhou 433*abe3a6eaShanjiezhou impl WindowId { 434*abe3a6eaShanjiezhou pub fn new() -> Self { 435*abe3a6eaShanjiezhou static MAX_ID: AtomicU32 = AtomicU32::new(0); 436*abe3a6eaShanjiezhou return WindowId(MAX_ID.fetch_add(1, Ordering::SeqCst)); 437*abe3a6eaShanjiezhou } 438*abe3a6eaShanjiezhou } 439*abe3a6eaShanjiezhou #[allow(dead_code)] 440*abe3a6eaShanjiezhou #[derive(Clone, Debug)] 441*abe3a6eaShanjiezhou pub struct TextuiWindow { 442*abe3a6eaShanjiezhou // 虚拟行是个循环表,头和尾相接 443*abe3a6eaShanjiezhou id: WindowId, 444*abe3a6eaShanjiezhou // 虚拟行总数 445*abe3a6eaShanjiezhou vline_sum: i32, 446*abe3a6eaShanjiezhou // 当前已经使用了的虚拟行总数(即在已经输入到缓冲区(之后显示在屏幕上)的虚拟行数量) 447*abe3a6eaShanjiezhou vlines_used: i32, 448*abe3a6eaShanjiezhou // 位于最顶上的那一个虚拟行的行号 449*abe3a6eaShanjiezhou top_vline: LineId, 450*abe3a6eaShanjiezhou // 储存虚拟行的数组 451*abe3a6eaShanjiezhou vlines: Vec<TextuiVline>, 452*abe3a6eaShanjiezhou // 正在操作的vline 453*abe3a6eaShanjiezhou vline_operating: LineId, 454*abe3a6eaShanjiezhou // 每行最大容纳的字符数 455*abe3a6eaShanjiezhou chars_per_line: i32, 456*abe3a6eaShanjiezhou // 窗口flag 457*abe3a6eaShanjiezhou flags: WindowFlag, 458*abe3a6eaShanjiezhou } 459*abe3a6eaShanjiezhou 460*abe3a6eaShanjiezhou impl TextuiWindow { 461*abe3a6eaShanjiezhou /// 使用参数初始化window对象 462*abe3a6eaShanjiezhou /// ## 参数 463*abe3a6eaShanjiezhou /// 464*abe3a6eaShanjiezhou /// -flags 标志位 465*abe3a6eaShanjiezhou /// -vlines_num 虚拟行的总数 466*abe3a6eaShanjiezhou /// -chars_num 每行最大的字符数 467*abe3a6eaShanjiezhou 468*abe3a6eaShanjiezhou pub fn new(flags: WindowFlag, vlines_num: i32, chars_num: i32) -> Self { 469*abe3a6eaShanjiezhou let mut initial_vlines = Vec::new(); 470*abe3a6eaShanjiezhou 471*abe3a6eaShanjiezhou for _ in 0..vlines_num { 472*abe3a6eaShanjiezhou let vline = TextuiVlineChromatic::new(chars_num as usize); 473*abe3a6eaShanjiezhou 474*abe3a6eaShanjiezhou initial_vlines.push(TextuiVline::Chromatic(vline)); 475*abe3a6eaShanjiezhou } 476*abe3a6eaShanjiezhou TextuiWindow { 477*abe3a6eaShanjiezhou id: WindowId::new(), 478*abe3a6eaShanjiezhou flags, 479*abe3a6eaShanjiezhou vline_sum: vlines_num, 480*abe3a6eaShanjiezhou vlines_used: 1, 481*abe3a6eaShanjiezhou top_vline: LineId::new(0), 482*abe3a6eaShanjiezhou vlines: initial_vlines, 483*abe3a6eaShanjiezhou vline_operating: LineId::new(0), 484*abe3a6eaShanjiezhou chars_per_line: chars_num, 485*abe3a6eaShanjiezhou } 486*abe3a6eaShanjiezhou } 487*abe3a6eaShanjiezhou 488*abe3a6eaShanjiezhou /// 刷新某个窗口的缓冲区的某个虚拟行的连续n个字符对象 489*abe3a6eaShanjiezhou /// ## 参数 490*abe3a6eaShanjiezhou /// - window 窗口结构体 491*abe3a6eaShanjiezhou /// - vline_id 要刷新的虚拟行号 492*abe3a6eaShanjiezhou /// - start 起始字符号 493*abe3a6eaShanjiezhou /// - count 要刷新的字符数量 494*abe3a6eaShanjiezhou 495*abe3a6eaShanjiezhou fn textui_refresh_characters( 496*abe3a6eaShanjiezhou &mut self, 497*abe3a6eaShanjiezhou vline_id: LineId, 498*abe3a6eaShanjiezhou start: LineIndex, 499*abe3a6eaShanjiezhou count: i32, 500*abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 501*abe3a6eaShanjiezhou let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst); 502*abe3a6eaShanjiezhou 503*abe3a6eaShanjiezhou // 判断虚拟行参数是否合法 504*abe3a6eaShanjiezhou if unlikely( 505*abe3a6eaShanjiezhou !vline_id.check(self.vline_sum) 506*abe3a6eaShanjiezhou || (<LineIndex as Into<i32>>::into(start) + count) > self.chars_per_line, 507*abe3a6eaShanjiezhou ) { 508*abe3a6eaShanjiezhou return Err(SystemError::EINVAL); 509*abe3a6eaShanjiezhou } 510*abe3a6eaShanjiezhou // 计算虚拟行对应的真实行(即要渲染的行) 511*abe3a6eaShanjiezhou let mut actual_line_id = vline_id - self.top_vline; //为正说明虚拟行不在真实行显示的区域上面 512*abe3a6eaShanjiezhou 513*abe3a6eaShanjiezhou if <LineId as Into<i32>>::into(actual_line_id) < 0 { 514*abe3a6eaShanjiezhou //真实行数小于虚拟行数,则需要加上真实行数的位置,以便正确计算真实行 515*abe3a6eaShanjiezhou actual_line_id = actual_line_id + actual_line_sum; 516*abe3a6eaShanjiezhou } 517*abe3a6eaShanjiezhou 518*abe3a6eaShanjiezhou // 将此窗口的某个虚拟行的连续n个字符对象往缓存区写入 519*abe3a6eaShanjiezhou if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 520*abe3a6eaShanjiezhou let vline = &mut self.vlines[<LineId as Into<usize>>::into(vline_id)]; 521*abe3a6eaShanjiezhou let mut i = 0; 522*abe3a6eaShanjiezhou let mut index = start; 523*abe3a6eaShanjiezhou 524*abe3a6eaShanjiezhou while i < count { 525*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = vline { 526*abe3a6eaShanjiezhou vline.chars[<LineIndex as Into<usize>>::into(index)] 527*abe3a6eaShanjiezhou .textui_refresh_character(actual_line_id, index)?; 528*abe3a6eaShanjiezhou 529*abe3a6eaShanjiezhou index = index + 1; 530*abe3a6eaShanjiezhou } 531*abe3a6eaShanjiezhou i += 1; 532*abe3a6eaShanjiezhou } 533*abe3a6eaShanjiezhou } 534*abe3a6eaShanjiezhou 535*abe3a6eaShanjiezhou return Ok(()); 536*abe3a6eaShanjiezhou } 537*abe3a6eaShanjiezhou 538*abe3a6eaShanjiezhou /// 重新渲染某个窗口的某个虚拟行 539*abe3a6eaShanjiezhou /// ## 参数 540*abe3a6eaShanjiezhou 541*abe3a6eaShanjiezhou /// - window 窗口结构体 542*abe3a6eaShanjiezhou /// - vline_id 虚拟行号 543*abe3a6eaShanjiezhou 544*abe3a6eaShanjiezhou fn textui_refresh_vline(&mut self, vline_id: LineId) -> Result<(), SystemError> { 545*abe3a6eaShanjiezhou if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 546*abe3a6eaShanjiezhou return self.textui_refresh_characters( 547*abe3a6eaShanjiezhou vline_id, 548*abe3a6eaShanjiezhou LineIndex::new(0), 549*abe3a6eaShanjiezhou self.chars_per_line, 550*abe3a6eaShanjiezhou ); 551*abe3a6eaShanjiezhou } else { 552*abe3a6eaShanjiezhou //todo支持纯文本字符() 553*abe3a6eaShanjiezhou todo!(); 554*abe3a6eaShanjiezhou } 555*abe3a6eaShanjiezhou } 556*abe3a6eaShanjiezhou 557*abe3a6eaShanjiezhou // 刷新某个窗口的start 到start + count行(即将这些行输入到缓冲区) 558*abe3a6eaShanjiezhou fn textui_refresh_vlines(&mut self, start: LineId, count: i32) -> Result<i32, SystemError> { 559*abe3a6eaShanjiezhou let mut refresh_count = count; 560*abe3a6eaShanjiezhou for i in <LineId as Into<i32>>::into(start) 561*abe3a6eaShanjiezhou ..(self.vline_sum).min(<LineId as Into<i32>>::into(start) + count) 562*abe3a6eaShanjiezhou { 563*abe3a6eaShanjiezhou self.textui_refresh_vline(LineId::new(i))?; 564*abe3a6eaShanjiezhou refresh_count -= 1; 565*abe3a6eaShanjiezhou } 566*abe3a6eaShanjiezhou //因为虚拟行是循环表 567*abe3a6eaShanjiezhou let mut refresh_start = 0; 568*abe3a6eaShanjiezhou while refresh_count > 0 { 569*abe3a6eaShanjiezhou self.textui_refresh_vline(LineId::new(refresh_start))?; 570*abe3a6eaShanjiezhou refresh_start += 1; 571*abe3a6eaShanjiezhou refresh_count -= 1; 572*abe3a6eaShanjiezhou } 573*abe3a6eaShanjiezhou return Ok(0); 574*abe3a6eaShanjiezhou } 575*abe3a6eaShanjiezhou 576*abe3a6eaShanjiezhou /// 往某个窗口的缓冲区的某个虚拟行插入换行 577*abe3a6eaShanjiezhou /// ## 参数 578*abe3a6eaShanjiezhou /// - window 窗口结构体 579*abe3a6eaShanjiezhou /// - vline_id 虚拟行号 580*abe3a6eaShanjiezhou 581*abe3a6eaShanjiezhou fn textui_new_line(&mut self) -> Result<i32, SystemError> { 582*abe3a6eaShanjiezhou // todo: 支持在两个虚拟行之间插入一个新行 583*abe3a6eaShanjiezhou let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst); 584*abe3a6eaShanjiezhou self.vline_operating = self.vline_operating + 1; 585*abe3a6eaShanjiezhou //如果已经到了最大行数,则重新从0开始 586*abe3a6eaShanjiezhou if !self.vline_operating.check(self.vline_sum) { 587*abe3a6eaShanjiezhou self.vline_operating = LineId::new(0); 588*abe3a6eaShanjiezhou } 589*abe3a6eaShanjiezhou 590*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 591*abe3a6eaShanjiezhou &mut (self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]) 592*abe3a6eaShanjiezhou { 593*abe3a6eaShanjiezhou for i in 0..self.chars_per_line { 594*abe3a6eaShanjiezhou if let Some(v_char) = vline.chars.get_mut(i as usize) { 595*abe3a6eaShanjiezhou v_char.c = None; 596*abe3a6eaShanjiezhou v_char.frcolor = FontColor::BLACK; 597*abe3a6eaShanjiezhou v_char.bkcolor = FontColor::BLACK; 598*abe3a6eaShanjiezhou } 599*abe3a6eaShanjiezhou } 600*abe3a6eaShanjiezhou vline.index = LineIndex::new(0); 601*abe3a6eaShanjiezhou } 602*abe3a6eaShanjiezhou // 当已经使用的虚拟行总数等于真实行总数时,说明窗口中已经显示的文本行数已经达到了窗口的最大容量。这时,如果继续在窗口中添加新的文本,就会导致文本溢出窗口而无法显示。因此,需要往下滚动屏幕来显示更多的文本。 603*abe3a6eaShanjiezhou 604*abe3a6eaShanjiezhou if self.vlines_used == actual_line_sum { 605*abe3a6eaShanjiezhou self.top_vline = self.top_vline + 1; 606*abe3a6eaShanjiezhou 607*abe3a6eaShanjiezhou if !self.top_vline.check(self.vline_sum) { 608*abe3a6eaShanjiezhou self.top_vline = LineId::new(0); 609*abe3a6eaShanjiezhou } 610*abe3a6eaShanjiezhou 611*abe3a6eaShanjiezhou // 刷新所有行 612*abe3a6eaShanjiezhou self.textui_refresh_vlines(self.top_vline, actual_line_sum)?; 613*abe3a6eaShanjiezhou } else { 614*abe3a6eaShanjiezhou //换行说明上一行已经在缓冲区中,所以已经使用的虚拟行总数+1 615*abe3a6eaShanjiezhou self.vlines_used += 1; 616*abe3a6eaShanjiezhou } 617*abe3a6eaShanjiezhou 618*abe3a6eaShanjiezhou return Ok(0); 619*abe3a6eaShanjiezhou } 620*abe3a6eaShanjiezhou 621*abe3a6eaShanjiezhou /// 真正向窗口的缓冲区上输入字符的函数(位置为window.vline_operating,window.vline_operating.index) 622*abe3a6eaShanjiezhou /// ## 参数 623*abe3a6eaShanjiezhou /// - window 624*abe3a6eaShanjiezhou /// - character 625*abe3a6eaShanjiezhou 626*abe3a6eaShanjiezhou fn true_textui_putchar_window( 627*abe3a6eaShanjiezhou &mut self, 628*abe3a6eaShanjiezhou character: char, 629*abe3a6eaShanjiezhou frcolor: FontColor, 630*abe3a6eaShanjiezhou bkcolor: FontColor, 631*abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 632*abe3a6eaShanjiezhou // 启用彩色字符 633*abe3a6eaShanjiezhou if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 634*abe3a6eaShanjiezhou let mut line_index = LineIndex::new(0); //操作的列号 635*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 636*abe3a6eaShanjiezhou &mut (self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]) 637*abe3a6eaShanjiezhou { 638*abe3a6eaShanjiezhou let index = <LineIndex as Into<usize>>::into(vline.index); 639*abe3a6eaShanjiezhou 640*abe3a6eaShanjiezhou if let Some(v_char) = vline.chars.get_mut(index) { 641*abe3a6eaShanjiezhou v_char.c = Some(character); 642*abe3a6eaShanjiezhou v_char.frcolor = frcolor; 643*abe3a6eaShanjiezhou v_char.bkcolor = bkcolor; 644*abe3a6eaShanjiezhou } 645*abe3a6eaShanjiezhou line_index = vline.index; 646*abe3a6eaShanjiezhou vline.index = vline.index + 1; 647*abe3a6eaShanjiezhou } 648*abe3a6eaShanjiezhou 649*abe3a6eaShanjiezhou self.textui_refresh_characters(self.vline_operating, line_index, 1)?; 650*abe3a6eaShanjiezhou 651*abe3a6eaShanjiezhou // 加入光标后,因为会识别光标,所以需超过该行最大字符数才能创建新行 652*abe3a6eaShanjiezhou if !line_index.check(self.chars_per_line - 1) { 653*abe3a6eaShanjiezhou self.textui_new_line()?; 654*abe3a6eaShanjiezhou } 655*abe3a6eaShanjiezhou } else { 656*abe3a6eaShanjiezhou // todo: 支持纯文本字符 657*abe3a6eaShanjiezhou todo!(); 658*abe3a6eaShanjiezhou } 659*abe3a6eaShanjiezhou return Ok(()); 660*abe3a6eaShanjiezhou } 661*abe3a6eaShanjiezhou /// 根据输入的一个字符在窗口上输出 662*abe3a6eaShanjiezhou /// ## 参数 663*abe3a6eaShanjiezhou 664*abe3a6eaShanjiezhou /// - window 窗口 665*abe3a6eaShanjiezhou /// - character 字符 666*abe3a6eaShanjiezhou /// - FRcolor 前景色(RGB) 667*abe3a6eaShanjiezhou /// - BKcolor 背景色(RGB) 668*abe3a6eaShanjiezhou 669*abe3a6eaShanjiezhou fn textui_putchar_window( 670*abe3a6eaShanjiezhou &mut self, 671*abe3a6eaShanjiezhou character: char, 672*abe3a6eaShanjiezhou frcolor: FontColor, 673*abe3a6eaShanjiezhou bkcolor: FontColor, 674*abe3a6eaShanjiezhou is_enable_window: bool, 675*abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 676*abe3a6eaShanjiezhou let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst); 677*abe3a6eaShanjiezhou 678*abe3a6eaShanjiezhou //字符'\0'代表ASCII码表中的空字符,表示字符串的结尾 679*abe3a6eaShanjiezhou if unlikely(character == '\0') { 680*abe3a6eaShanjiezhou return Ok(()); 681*abe3a6eaShanjiezhou } 682*abe3a6eaShanjiezhou 683*abe3a6eaShanjiezhou if unlikely(character == '\r') { 684*abe3a6eaShanjiezhou return Ok(()); 685*abe3a6eaShanjiezhou } 686*abe3a6eaShanjiezhou 687*abe3a6eaShanjiezhou // 暂不支持纯文本窗口 688*abe3a6eaShanjiezhou if !self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) { 689*abe3a6eaShanjiezhou return Ok(()); 690*abe3a6eaShanjiezhou } 691*abe3a6eaShanjiezhou 692*abe3a6eaShanjiezhou //进行换行操作 693*abe3a6eaShanjiezhou if character == '\n' { 694*abe3a6eaShanjiezhou // 换行时还需要输出\r 695*abe3a6eaShanjiezhou c_uart_send(UartPort::COM1.to_u16(), b'\r'); 696*abe3a6eaShanjiezhou if is_enable_window == true { 697*abe3a6eaShanjiezhou self.textui_new_line()?; 698*abe3a6eaShanjiezhou } 699*abe3a6eaShanjiezhou return Ok(()); 700*abe3a6eaShanjiezhou } 701*abe3a6eaShanjiezhou // 输出制表符 702*abe3a6eaShanjiezhou else if character == '\t' { 703*abe3a6eaShanjiezhou if is_enable_window == true { 704*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 705*abe3a6eaShanjiezhou &self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 706*abe3a6eaShanjiezhou { 707*abe3a6eaShanjiezhou //打印的空格数(注意将每行分成一个个表格,每个表格为8个字符) 708*abe3a6eaShanjiezhou let mut space_to_print = 8 - <LineIndex as Into<usize>>::into(vline.index) % 8; 709*abe3a6eaShanjiezhou while space_to_print > 0 { 710*abe3a6eaShanjiezhou self.true_textui_putchar_window(' ', frcolor, bkcolor)?; 711*abe3a6eaShanjiezhou space_to_print -= 1; 712*abe3a6eaShanjiezhou } 713*abe3a6eaShanjiezhou } 714*abe3a6eaShanjiezhou } 715*abe3a6eaShanjiezhou } 716*abe3a6eaShanjiezhou // 字符 '\x08' 代表 ASCII 码中的退格字符。它在输出中的作用是将光标向左移动一个位置,并在该位置上输出后续的字符,从而实现字符的删除或替换。 717*abe3a6eaShanjiezhou else if character == '\x08' { 718*abe3a6eaShanjiezhou if is_enable_window == true { 719*abe3a6eaShanjiezhou let mut tmp = LineIndex(0); 720*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 721*abe3a6eaShanjiezhou &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 722*abe3a6eaShanjiezhou { 723*abe3a6eaShanjiezhou vline.index = vline.index - 1; 724*abe3a6eaShanjiezhou tmp = vline.index; 725*abe3a6eaShanjiezhou } 726*abe3a6eaShanjiezhou if <LineIndex as Into<i32>>::into(tmp) >= 0 { 727*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 728*abe3a6eaShanjiezhou &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 729*abe3a6eaShanjiezhou { 730*abe3a6eaShanjiezhou if let Some(v_char) = 731*abe3a6eaShanjiezhou vline.chars.get_mut(<LineIndex as Into<usize>>::into(tmp)) 732*abe3a6eaShanjiezhou { 733*abe3a6eaShanjiezhou v_char.c = Some(' '); 734*abe3a6eaShanjiezhou 735*abe3a6eaShanjiezhou v_char.bkcolor = bkcolor; 736*abe3a6eaShanjiezhou } 737*abe3a6eaShanjiezhou } 738*abe3a6eaShanjiezhou return self.textui_refresh_characters(self.vline_operating, tmp, 1); 739*abe3a6eaShanjiezhou } 740*abe3a6eaShanjiezhou // 需要向上缩一行 741*abe3a6eaShanjiezhou if <LineIndex as Into<i32>>::into(tmp) < 0 { 742*abe3a6eaShanjiezhou // 当前行为空,需要重新刷新 743*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 744*abe3a6eaShanjiezhou &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 745*abe3a6eaShanjiezhou { 746*abe3a6eaShanjiezhou vline.index = LineIndex::new(0); 747*abe3a6eaShanjiezhou for i in 0..self.chars_per_line { 748*abe3a6eaShanjiezhou if let Some(v_char) = vline.chars.get_mut(i as usize) { 749*abe3a6eaShanjiezhou v_char.c = None; 750*abe3a6eaShanjiezhou v_char.frcolor = FontColor::BLACK; 751*abe3a6eaShanjiezhou v_char.bkcolor = FontColor::BLACK; 752*abe3a6eaShanjiezhou } 753*abe3a6eaShanjiezhou } 754*abe3a6eaShanjiezhou } 755*abe3a6eaShanjiezhou // 上缩一行 756*abe3a6eaShanjiezhou self.vline_operating = self.vline_operating - 1; 757*abe3a6eaShanjiezhou if self.vline_operating.data() < 0 { 758*abe3a6eaShanjiezhou self.vline_operating = LineId(self.vline_sum - 1); 759*abe3a6eaShanjiezhou } 760*abe3a6eaShanjiezhou 761*abe3a6eaShanjiezhou // 考虑是否向上滚动(在top_vline上退格) 762*abe3a6eaShanjiezhou if self.vlines_used > actual_line_sum { 763*abe3a6eaShanjiezhou self.top_vline = self.top_vline - 1; 764*abe3a6eaShanjiezhou if <LineId as Into<i32>>::into(self.top_vline) < 0 { 765*abe3a6eaShanjiezhou self.top_vline = LineId(self.vline_sum - 1); 766*abe3a6eaShanjiezhou } 767*abe3a6eaShanjiezhou } 768*abe3a6eaShanjiezhou //因为上缩一行所以显示在屏幕中的虚拟行少一 769*abe3a6eaShanjiezhou self.vlines_used -= 1; 770*abe3a6eaShanjiezhou self.textui_refresh_vlines(self.top_vline, actual_line_sum)?; 771*abe3a6eaShanjiezhou } 772*abe3a6eaShanjiezhou } 773*abe3a6eaShanjiezhou } else { 774*abe3a6eaShanjiezhou // 输出其他字符 775*abe3a6eaShanjiezhou 776*abe3a6eaShanjiezhou c_uart_send(UartPort::COM1.to_u16(), character as u8); 777*abe3a6eaShanjiezhou 778*abe3a6eaShanjiezhou if is_enable_window == true { 779*abe3a6eaShanjiezhou if let TextuiVline::Chromatic(vline) = 780*abe3a6eaShanjiezhou &self.vlines[<LineId as Into<usize>>::into(self.vline_operating)] 781*abe3a6eaShanjiezhou { 782*abe3a6eaShanjiezhou if !vline.index.check(self.chars_per_line) { 783*abe3a6eaShanjiezhou self.textui_new_line()?; 784*abe3a6eaShanjiezhou } 785*abe3a6eaShanjiezhou 786*abe3a6eaShanjiezhou return self.true_textui_putchar_window(character, frcolor, bkcolor); 787*abe3a6eaShanjiezhou } 788*abe3a6eaShanjiezhou } 789*abe3a6eaShanjiezhou } 790*abe3a6eaShanjiezhou 791*abe3a6eaShanjiezhou return Ok(()); 792*abe3a6eaShanjiezhou } 793*abe3a6eaShanjiezhou } 794*abe3a6eaShanjiezhou impl Default for TextuiWindow { 795*abe3a6eaShanjiezhou fn default() -> Self { 796*abe3a6eaShanjiezhou TextuiWindow { 797*abe3a6eaShanjiezhou id: WindowId(0), 798*abe3a6eaShanjiezhou flags: WindowFlag::TEXTUI_CHROMATIC, 799*abe3a6eaShanjiezhou vline_sum: 0, 800*abe3a6eaShanjiezhou vlines_used: 1, 801*abe3a6eaShanjiezhou top_vline: LineId::new(0), 802*abe3a6eaShanjiezhou vlines: Vec::new(), 803*abe3a6eaShanjiezhou vline_operating: LineId::new(0), 804*abe3a6eaShanjiezhou chars_per_line: 0, 805*abe3a6eaShanjiezhou } 806*abe3a6eaShanjiezhou } 807*abe3a6eaShanjiezhou } 808*abe3a6eaShanjiezhou #[allow(dead_code)] 809*abe3a6eaShanjiezhou #[derive(Debug)] 810*abe3a6eaShanjiezhou pub struct TextUiFramework { 811*abe3a6eaShanjiezhou metadata: ScmUiFrameworkMetadata, 812*abe3a6eaShanjiezhou window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>>, 813*abe3a6eaShanjiezhou actual_line: AtomicI32, // 真实行的数量(textui的帧缓冲区能容纳的内容的行数) 814*abe3a6eaShanjiezhou current_window: Arc<SpinLock<TextuiWindow>>, // 当前的主窗口 815*abe3a6eaShanjiezhou default_window: Arc<SpinLock<TextuiWindow>>, // 默认print到的窗口 816*abe3a6eaShanjiezhou } 817*abe3a6eaShanjiezhou 818*abe3a6eaShanjiezhou impl TextUiFramework { 819*abe3a6eaShanjiezhou pub fn new( 820*abe3a6eaShanjiezhou metadata: ScmUiFrameworkMetadata, 821*abe3a6eaShanjiezhou window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>>, 822*abe3a6eaShanjiezhou current_window: Arc<SpinLock<TextuiWindow>>, 823*abe3a6eaShanjiezhou default_window: Arc<SpinLock<TextuiWindow>>, 824*abe3a6eaShanjiezhou ) -> Self { 825*abe3a6eaShanjiezhou let actual_line = 826*abe3a6eaShanjiezhou AtomicI32::new((&metadata.buf_info().buf_height() / TEXTUI_CHAR_HEIGHT) as i32); 827*abe3a6eaShanjiezhou let inner = TextUiFramework { 828*abe3a6eaShanjiezhou metadata, 829*abe3a6eaShanjiezhou window_list, 830*abe3a6eaShanjiezhou actual_line, 831*abe3a6eaShanjiezhou current_window, 832*abe3a6eaShanjiezhou default_window, 833*abe3a6eaShanjiezhou }; 834*abe3a6eaShanjiezhou return inner; 835*abe3a6eaShanjiezhou } 836*abe3a6eaShanjiezhou } 837*abe3a6eaShanjiezhou 838*abe3a6eaShanjiezhou impl ScmUiFramework for &mut TextUiFramework { 839*abe3a6eaShanjiezhou // 安装ui框架的回调函数 840*abe3a6eaShanjiezhou fn install(&self) -> Result<i32, SystemError> { 841*abe3a6eaShanjiezhou c_uart_send_str( 842*abe3a6eaShanjiezhou UartPort::COM1.to_u16(), 843*abe3a6eaShanjiezhou "\ntextui_install_handler\n\0".as_ptr(), 844*abe3a6eaShanjiezhou ); 845*abe3a6eaShanjiezhou return Ok(0); 846*abe3a6eaShanjiezhou } 847*abe3a6eaShanjiezhou // 卸载ui框架的回调函数 848*abe3a6eaShanjiezhou fn uninstall(&self) -> Result<i32, SystemError> { 849*abe3a6eaShanjiezhou return Ok(0); 850*abe3a6eaShanjiezhou } 851*abe3a6eaShanjiezhou // 启用ui框架的回调函数 852*abe3a6eaShanjiezhou fn enable(&self) -> Result<i32, SystemError> { 853*abe3a6eaShanjiezhou ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst); 854*abe3a6eaShanjiezhou return Ok(0); 855*abe3a6eaShanjiezhou } 856*abe3a6eaShanjiezhou // 禁用ui框架的回调函数 857*abe3a6eaShanjiezhou fn disable(&self) -> Result<i32, SystemError> { 858*abe3a6eaShanjiezhou ENABLE_PUT_TO_WINDOW.store(false, Ordering::SeqCst); 859*abe3a6eaShanjiezhou 860*abe3a6eaShanjiezhou return Ok(0); 861*abe3a6eaShanjiezhou } 862*abe3a6eaShanjiezhou // 改变ui框架的帧缓冲区的回调函数 863*abe3a6eaShanjiezhou fn change(&self, buf_info: ScmBufferInfo) -> Result<i32, SystemError> { 864*abe3a6eaShanjiezhou let src_buf = textui_framework().metadata.buf(); 865*abe3a6eaShanjiezhou textui_framework().metadata.set_buf_info(buf_info); 866*abe3a6eaShanjiezhou let dst_buf = textui_framework().metadata.buf(); 867*abe3a6eaShanjiezhou dst_buf.copy_from_slice(src_buf); 868*abe3a6eaShanjiezhou return Ok(0); 869*abe3a6eaShanjiezhou } 870*abe3a6eaShanjiezhou /// 获取ScmUiFramework的元数据 871*abe3a6eaShanjiezhou /// ## 返回值 872*abe3a6eaShanjiezhou /// 873*abe3a6eaShanjiezhou /// -成功:Ok(ScmUiFramework的元数据) 874*abe3a6eaShanjiezhou /// -失败:Err(错误码) 875*abe3a6eaShanjiezhou fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> { 876*abe3a6eaShanjiezhou let metadata = self.metadata.clone(); 877*abe3a6eaShanjiezhou 878*abe3a6eaShanjiezhou return Ok(metadata); 879*abe3a6eaShanjiezhou } 880*abe3a6eaShanjiezhou } 881*abe3a6eaShanjiezhou 882*abe3a6eaShanjiezhou /// Mapping from characters to glyph indices. 883*abe3a6eaShanjiezhou pub trait GlyphMapping: Sync { 884*abe3a6eaShanjiezhou /// Maps a character to a glyph index. 885*abe3a6eaShanjiezhou /// 886*abe3a6eaShanjiezhou /// If `c` isn't included in the font the index of a suitable replacement glyph is returned. 887*abe3a6eaShanjiezhou fn index(&self, c: char) -> usize; 888*abe3a6eaShanjiezhou } 889*abe3a6eaShanjiezhou 890*abe3a6eaShanjiezhou impl<F> GlyphMapping for F 891*abe3a6eaShanjiezhou where 892*abe3a6eaShanjiezhou F: Sync + Fn(char) -> usize, 893*abe3a6eaShanjiezhou { 894*abe3a6eaShanjiezhou fn index(&self, c: char) -> usize { 895*abe3a6eaShanjiezhou self(c) 896*abe3a6eaShanjiezhou } 897*abe3a6eaShanjiezhou } 898*abe3a6eaShanjiezhou 899*abe3a6eaShanjiezhou /// 在默认窗口上输出一个字符 900*abe3a6eaShanjiezhou /// ## 参数 901*abe3a6eaShanjiezhou /// - character 字符 902*abe3a6eaShanjiezhou /// - FRcolor 前景色(RGB) 903*abe3a6eaShanjiezhou /// - BKcolor 背景色(RGB) 904*abe3a6eaShanjiezhou 905*abe3a6eaShanjiezhou #[no_mangle] 906*abe3a6eaShanjiezhou pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32) -> i32 { 907*abe3a6eaShanjiezhou return textui_putchar( 908*abe3a6eaShanjiezhou character as char, 909*abe3a6eaShanjiezhou FontColor::from(fr_color), 910*abe3a6eaShanjiezhou FontColor::from(bk_color), 911*abe3a6eaShanjiezhou ) 912*abe3a6eaShanjiezhou .map(|_| 0) 913*abe3a6eaShanjiezhou .unwrap_or_else(|e| e.to_posix_errno()); 914*abe3a6eaShanjiezhou } 915*abe3a6eaShanjiezhou 916*abe3a6eaShanjiezhou pub fn textui_putchar( 917*abe3a6eaShanjiezhou character: char, 918*abe3a6eaShanjiezhou fr_color: FontColor, 919*abe3a6eaShanjiezhou bk_color: FontColor, 920*abe3a6eaShanjiezhou ) -> Result<(), SystemError> { 921*abe3a6eaShanjiezhou if unsafe { TEXTUI_IS_INIT } { 922*abe3a6eaShanjiezhou return textui_framework() 923*abe3a6eaShanjiezhou .current_window 924*abe3a6eaShanjiezhou .lock() 925*abe3a6eaShanjiezhou .textui_putchar_window( 926*abe3a6eaShanjiezhou character, 927*abe3a6eaShanjiezhou fr_color, 928*abe3a6eaShanjiezhou bk_color, 929*abe3a6eaShanjiezhou ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst), 930*abe3a6eaShanjiezhou ); 931*abe3a6eaShanjiezhou } else { 932*abe3a6eaShanjiezhou //未初始化暴力输出 933*abe3a6eaShanjiezhou return no_init_textui_putchar_window( 934*abe3a6eaShanjiezhou character, 935*abe3a6eaShanjiezhou fr_color, 936*abe3a6eaShanjiezhou bk_color, 937*abe3a6eaShanjiezhou ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst), 938*abe3a6eaShanjiezhou ); 939*abe3a6eaShanjiezhou } 940*abe3a6eaShanjiezhou } 941*abe3a6eaShanjiezhou 942*abe3a6eaShanjiezhou /// 初始化text ui框架 943*abe3a6eaShanjiezhou 944*abe3a6eaShanjiezhou #[no_mangle] 945*abe3a6eaShanjiezhou pub extern "C" fn rs_textui_init() -> i32 { 946*abe3a6eaShanjiezhou let r = textui_init().unwrap_or_else(|e| e.to_posix_errno()); 947*abe3a6eaShanjiezhou if r.is_negative() { 948*abe3a6eaShanjiezhou c_uart_send_str(UartPort::COM1.to_u16(), "textui init failed.\n\0".as_ptr()); 949*abe3a6eaShanjiezhou } 950*abe3a6eaShanjiezhou return r; 951*abe3a6eaShanjiezhou } 952*abe3a6eaShanjiezhou 953*abe3a6eaShanjiezhou fn textui_init() -> Result<i32, SystemError> { 954*abe3a6eaShanjiezhou unsafe { textui_framwork_init() }; 955*abe3a6eaShanjiezhou let textui_framework = textui_framework(); 956*abe3a6eaShanjiezhou 957*abe3a6eaShanjiezhou unsafe { TEXTUI_IS_INIT = true }; 958*abe3a6eaShanjiezhou 959*abe3a6eaShanjiezhou scm_register(Arc::new(textui_framework))?; 960*abe3a6eaShanjiezhou 961*abe3a6eaShanjiezhou c_uart_send_str( 962*abe3a6eaShanjiezhou UartPort::COM1.to_u16(), 963*abe3a6eaShanjiezhou "\ntext ui initialized\n\0".as_ptr(), 964*abe3a6eaShanjiezhou ); 965*abe3a6eaShanjiezhou 966*abe3a6eaShanjiezhou return Ok(0); 967*abe3a6eaShanjiezhou } 968