xref: /DragonOS/kernel/src/libs/lib_ui/textui.rs (revision abe3a6ea3c543425e2cad12722e8a658b324d515)
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