xref: /DragonOS/kernel/src/libs/lib_ui/textui.rs (revision e28411791f090c421fe4b6fa5956fb1bd362a8d9)
1abe3a6eaShanjiezhou use crate::{
21496ba7bSLoGin     driver::{
352da9a59SGnoCiYeH         serial::serial8250::send_to_default_serial8250_port,
452da9a59SGnoCiYeH         tty::{
552da9a59SGnoCiYeH             tty_driver::TtyOperation, tty_port::TTY_PORTS,
652da9a59SGnoCiYeH             virtual_terminal::virtual_console::CURRENT_VCNUM,
752da9a59SGnoCiYeH         },
852da9a59SGnoCiYeH         video::video_refresh_manager,
91496ba7bSLoGin     },
101496ba7bSLoGin     kdebug, kinfo,
111496ba7bSLoGin     libs::{
121496ba7bSLoGin         lib_ui::font::FONT_8x16,
131496ba7bSLoGin         rwlock::RwLock,
141496ba7bSLoGin         spinlock::{SpinLock, SpinLockGuard},
151496ba7bSLoGin     },
16abe3a6eaShanjiezhou };
17abe3a6eaShanjiezhou use alloc::{boxed::Box, collections::LinkedList, string::ToString};
18abe3a6eaShanjiezhou use alloc::{sync::Arc, vec::Vec};
19abe3a6eaShanjiezhou use core::{
20abe3a6eaShanjiezhou     fmt::Debug,
21abe3a6eaShanjiezhou     intrinsics::unlikely,
22abe3a6eaShanjiezhou     ops::{Add, AddAssign, Sub},
23abe3a6eaShanjiezhou     sync::atomic::{AtomicBool, AtomicI32, AtomicU32, Ordering},
24abe3a6eaShanjiezhou };
2591e9d4abSLoGin use system_error::SystemError;
26abe3a6eaShanjiezhou 
27abe3a6eaShanjiezhou use super::{
28abe3a6eaShanjiezhou     screen_manager::{
291496ba7bSLoGin         scm_register, ScmBuffer, ScmBufferInfo, ScmFramworkType, ScmUiFramework,
301496ba7bSLoGin         ScmUiFrameworkMetadata,
31abe3a6eaShanjiezhou     },
32abe3a6eaShanjiezhou     textui_no_alloc::no_init_textui_putchar_window,
33abe3a6eaShanjiezhou };
34abe3a6eaShanjiezhou 
35abe3a6eaShanjiezhou /// 声明全局的TEXTUI_FRAMEWORK
361496ba7bSLoGin static mut __TEXTUI_FRAMEWORK: Option<Arc<TextUiFramework>> = None;
37abe3a6eaShanjiezhou 
38abe3a6eaShanjiezhou /// 每个字符的宽度和高度(像素)
39abe3a6eaShanjiezhou pub const TEXTUI_CHAR_WIDTH: u32 = 8;
40abe3a6eaShanjiezhou 
41abe3a6eaShanjiezhou pub const TEXTUI_CHAR_HEIGHT: u32 = 16;
42abe3a6eaShanjiezhou 
43abe3a6eaShanjiezhou pub static mut TEXTUI_IS_INIT: bool = false;
44abe3a6eaShanjiezhou 
451a72a751SLoGin static ENABLE_PUT_TO_WINDOW: AtomicBool = AtomicBool::new(false);
461a72a751SLoGin 
471a72a751SLoGin /// 启用将文本输出到窗口的功能。
481a72a751SLoGin pub fn textui_enable_put_to_window() {
491a72a751SLoGin     ENABLE_PUT_TO_WINDOW.store(true, Ordering::SeqCst);
501a72a751SLoGin }
511a72a751SLoGin 
521a72a751SLoGin /// 禁用将文本输出到窗口的功能。
531a72a751SLoGin pub fn textui_disable_put_to_window() {
541a72a751SLoGin     ENABLE_PUT_TO_WINDOW.store(false, Ordering::SeqCst);
551a72a751SLoGin }
561a72a751SLoGin 
571a72a751SLoGin /// 检查是否启用了将文本输出到窗口的功能。
581a72a751SLoGin ///
591a72a751SLoGin /// # 返回
601a72a751SLoGin /// 如果启用了将文本输出到窗口的功能,则返回 `true`,否则返回 `false`。
611a72a751SLoGin pub fn textui_is_enable_put_to_window() -> bool {
621a72a751SLoGin     ENABLE_PUT_TO_WINDOW.load(Ordering::SeqCst)
631a72a751SLoGin }
64abe3a6eaShanjiezhou 
65abe3a6eaShanjiezhou /// 获取TEXTUI_FRAMEWORK的可变实例
661496ba7bSLoGin pub fn textui_framework() -> Arc<TextUiFramework> {
671496ba7bSLoGin     unsafe {
681496ba7bSLoGin         return __TEXTUI_FRAMEWORK
691496ba7bSLoGin             .as_ref()
701496ba7bSLoGin             .expect("Textui framework has not been initialized yet!")
711496ba7bSLoGin             .clone();
72abe3a6eaShanjiezhou     }
731496ba7bSLoGin }
741496ba7bSLoGin 
75abe3a6eaShanjiezhou /// 初始化TEXTUI_FRAMEWORK
765b59005fSLoGin fn textui_framwork_init() {
775b59005fSLoGin     if unsafe { __TEXTUI_FRAMEWORK.is_none() } {
78abe3a6eaShanjiezhou         kinfo!("textuiframework init");
79abe3a6eaShanjiezhou         let metadata = ScmUiFrameworkMetadata::new("TextUI".to_string(), ScmFramworkType::Text);
801496ba7bSLoGin         kdebug!("textui metadata: {:?}", metadata);
81abe3a6eaShanjiezhou         // 为textui框架生成第一个窗口
821496ba7bSLoGin         let vlines_num = (metadata.buf_info().height() / TEXTUI_CHAR_HEIGHT) as usize;
83abe3a6eaShanjiezhou 
841496ba7bSLoGin         let chars_num = (metadata.buf_info().width() / TEXTUI_CHAR_WIDTH) as usize;
85abe3a6eaShanjiezhou 
86abe3a6eaShanjiezhou         let initial_window = TextuiWindow::new(
87abe3a6eaShanjiezhou             WindowFlag::TEXTUI_CHROMATIC,
88abe3a6eaShanjiezhou             vlines_num as i32,
89abe3a6eaShanjiezhou             chars_num as i32,
90abe3a6eaShanjiezhou         );
91abe3a6eaShanjiezhou 
92abe3a6eaShanjiezhou         let current_window: Arc<SpinLock<TextuiWindow>> = Arc::new(SpinLock::new(initial_window));
93abe3a6eaShanjiezhou 
94abe3a6eaShanjiezhou         let default_window = current_window.clone();
95abe3a6eaShanjiezhou 
96abe3a6eaShanjiezhou         // 生成窗口链表,并把上面窗口添加进textui框架的窗口链表中
97abe3a6eaShanjiezhou         let window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>> =
98abe3a6eaShanjiezhou             Arc::new(SpinLock::new(LinkedList::new()));
99abe3a6eaShanjiezhou         window_list.lock().push_back(current_window.clone());
100abe3a6eaShanjiezhou 
1015b59005fSLoGin         unsafe {
1021496ba7bSLoGin             __TEXTUI_FRAMEWORK = Some(Arc::new(TextUiFramework::new(
103abe3a6eaShanjiezhou                 metadata,
104abe3a6eaShanjiezhou                 window_list,
105abe3a6eaShanjiezhou                 current_window,
106abe3a6eaShanjiezhou                 default_window,
1075b59005fSLoGin             )))
1085b59005fSLoGin         };
1091496ba7bSLoGin 
1101496ba7bSLoGin         scm_register(textui_framework()).expect("register textui framework failed");
1111496ba7bSLoGin         kdebug!("textui framework init success");
1121496ba7bSLoGin 
113a03c4f9dSLoGin         send_to_default_serial8250_port("\ntext ui initialized\n\0".as_bytes());
1141496ba7bSLoGin         unsafe { TEXTUI_IS_INIT = true };
115abe3a6eaShanjiezhou     } else {
116abe3a6eaShanjiezhou         panic!("Try to init TEXTUI_FRAMEWORK twice!");
117abe3a6eaShanjiezhou     }
118abe3a6eaShanjiezhou }
119abe3a6eaShanjiezhou // window标志位
120abe3a6eaShanjiezhou bitflags! {
121abe3a6eaShanjiezhou     pub struct WindowFlag: u8 {
122abe3a6eaShanjiezhou         // 采用彩色字符
123abe3a6eaShanjiezhou         const TEXTUI_CHROMATIC = 1 << 0;
124abe3a6eaShanjiezhou     }
125abe3a6eaShanjiezhou }
126abe3a6eaShanjiezhou 
127abe3a6eaShanjiezhou /**
128abe3a6eaShanjiezhou  * @brief 黑白字符对象
129abe3a6eaShanjiezhou  *
130abe3a6eaShanjiezhou  */
131abe3a6eaShanjiezhou #[derive(Clone, Debug)]
132abe3a6eaShanjiezhou struct TextuiCharNormal {
133abe3a6eaShanjiezhou     _data: u8,
134abe3a6eaShanjiezhou }
135abe3a6eaShanjiezhou 
136abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)]
137abe3a6eaShanjiezhou pub struct LineId(i32);
138abe3a6eaShanjiezhou impl LineId {
139abe3a6eaShanjiezhou     pub fn new(num: i32) -> Self {
140abe3a6eaShanjiezhou         LineId(num)
141abe3a6eaShanjiezhou     }
142abe3a6eaShanjiezhou 
143abe3a6eaShanjiezhou     pub fn check(&self, max: i32) -> bool {
144abe3a6eaShanjiezhou         self.0 < max && self.0 >= 0
145abe3a6eaShanjiezhou     }
146abe3a6eaShanjiezhou 
147abe3a6eaShanjiezhou     pub fn data(&self) -> i32 {
148abe3a6eaShanjiezhou         self.0
149abe3a6eaShanjiezhou     }
150abe3a6eaShanjiezhou }
151abe3a6eaShanjiezhou impl Add<i32> for LineId {
152abe3a6eaShanjiezhou     type Output = LineId;
153abe3a6eaShanjiezhou     fn add(self, rhs: i32) -> Self::Output {
154abe3a6eaShanjiezhou         LineId::new(self.0 + rhs)
155abe3a6eaShanjiezhou     }
156abe3a6eaShanjiezhou }
157abe3a6eaShanjiezhou impl Sub<i32> for LineId {
158abe3a6eaShanjiezhou     type Output = LineId;
159abe3a6eaShanjiezhou 
160abe3a6eaShanjiezhou     fn sub(self, rhs: i32) -> Self::Output {
161abe3a6eaShanjiezhou         LineId::new(self.0 - rhs)
162abe3a6eaShanjiezhou     }
163abe3a6eaShanjiezhou }
164abe3a6eaShanjiezhou 
165abe3a6eaShanjiezhou impl Into<i32> for LineId {
166abe3a6eaShanjiezhou     fn into(self) -> i32 {
167abe3a6eaShanjiezhou         self.0.clone()
168abe3a6eaShanjiezhou     }
169abe3a6eaShanjiezhou }
170abe3a6eaShanjiezhou impl Into<u32> for LineId {
171abe3a6eaShanjiezhou     fn into(self) -> u32 {
172abe3a6eaShanjiezhou         self.0.clone() as u32
173abe3a6eaShanjiezhou     }
174abe3a6eaShanjiezhou }
175abe3a6eaShanjiezhou impl Into<usize> for LineId {
176abe3a6eaShanjiezhou     fn into(self) -> usize {
177abe3a6eaShanjiezhou         self.0.clone() as usize
178abe3a6eaShanjiezhou     }
179abe3a6eaShanjiezhou }
180abe3a6eaShanjiezhou impl Sub<LineId> for LineId {
181abe3a6eaShanjiezhou     type Output = LineId;
182abe3a6eaShanjiezhou 
183abe3a6eaShanjiezhou     fn sub(mut self, rhs: LineId) -> Self::Output {
184abe3a6eaShanjiezhou         self.0 -= rhs.0;
185abe3a6eaShanjiezhou         return self;
186abe3a6eaShanjiezhou     }
187abe3a6eaShanjiezhou }
188abe3a6eaShanjiezhou impl AddAssign<LineId> for LineId {
189abe3a6eaShanjiezhou     fn add_assign(&mut self, rhs: LineId) {
190abe3a6eaShanjiezhou         self.0 += rhs.0;
191abe3a6eaShanjiezhou     }
192abe3a6eaShanjiezhou }
193abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash, Default)]
194abe3a6eaShanjiezhou pub struct LineIndex(i32);
195abe3a6eaShanjiezhou impl LineIndex {
196abe3a6eaShanjiezhou     pub fn new(num: i32) -> Self {
197abe3a6eaShanjiezhou         LineIndex(num)
198abe3a6eaShanjiezhou     }
199abe3a6eaShanjiezhou     pub fn check(&self, chars_per_line: i32) -> bool {
200abe3a6eaShanjiezhou         self.0 < chars_per_line && self.0 >= 0
201abe3a6eaShanjiezhou     }
202abe3a6eaShanjiezhou }
203abe3a6eaShanjiezhou impl Add<LineIndex> for LineIndex {
204abe3a6eaShanjiezhou     type Output = LineIndex;
205abe3a6eaShanjiezhou 
206abe3a6eaShanjiezhou     fn add(self, rhs: LineIndex) -> Self::Output {
207abe3a6eaShanjiezhou         LineIndex::new(self.0 + rhs.0)
208abe3a6eaShanjiezhou     }
209abe3a6eaShanjiezhou }
210abe3a6eaShanjiezhou impl Add<i32> for LineIndex {
211abe3a6eaShanjiezhou     // type Output = Self;
212abe3a6eaShanjiezhou     type Output = LineIndex;
213abe3a6eaShanjiezhou 
214abe3a6eaShanjiezhou     fn add(self, rhs: i32) -> Self::Output {
215abe3a6eaShanjiezhou         LineIndex::new(self.0 + rhs)
216abe3a6eaShanjiezhou     }
217abe3a6eaShanjiezhou }
218abe3a6eaShanjiezhou impl Sub<i32> for LineIndex {
219abe3a6eaShanjiezhou     type Output = LineIndex;
220abe3a6eaShanjiezhou 
221abe3a6eaShanjiezhou     fn sub(self, rhs: i32) -> Self::Output {
222abe3a6eaShanjiezhou         LineIndex::new(self.0 - rhs)
223abe3a6eaShanjiezhou     }
224abe3a6eaShanjiezhou }
225abe3a6eaShanjiezhou 
226abe3a6eaShanjiezhou impl Into<i32> for LineIndex {
227abe3a6eaShanjiezhou     fn into(self) -> i32 {
228abe3a6eaShanjiezhou         self.0.clone()
229abe3a6eaShanjiezhou     }
230abe3a6eaShanjiezhou }
231abe3a6eaShanjiezhou impl Into<u32> for LineIndex {
232abe3a6eaShanjiezhou     fn into(self) -> u32 {
233abe3a6eaShanjiezhou         self.0.clone() as u32
234abe3a6eaShanjiezhou     }
235abe3a6eaShanjiezhou }
236abe3a6eaShanjiezhou impl Into<usize> for LineIndex {
237abe3a6eaShanjiezhou     fn into(self) -> usize {
238abe3a6eaShanjiezhou         self.0.clone() as usize
239abe3a6eaShanjiezhou     }
240abe3a6eaShanjiezhou }
241abe3a6eaShanjiezhou #[derive(Copy, Clone, Debug)]
242abe3a6eaShanjiezhou pub struct FontColor(u32);
243abe3a6eaShanjiezhou #[allow(dead_code)]
244abe3a6eaShanjiezhou impl FontColor {
245abe3a6eaShanjiezhou     pub const BLUE: FontColor = FontColor::new(0, 0, 0xff);
246abe3a6eaShanjiezhou     pub const RED: FontColor = FontColor::new(0xff, 0, 0);
247abe3a6eaShanjiezhou     pub const GREEN: FontColor = FontColor::new(0, 0xff, 0);
248abe3a6eaShanjiezhou     pub const WHITE: FontColor = FontColor::new(0xff, 0xff, 0xff);
249abe3a6eaShanjiezhou     pub const BLACK: FontColor = FontColor::new(0, 0, 0);
250abe3a6eaShanjiezhou     pub const YELLOW: FontColor = FontColor::new(0xff, 0xff, 0);
251abe3a6eaShanjiezhou     pub const ORANGE: FontColor = FontColor::new(0xff, 0x80, 0);
252abe3a6eaShanjiezhou     pub const INDIGO: FontColor = FontColor::new(0x00, 0xff, 0xff);
253abe3a6eaShanjiezhou     pub const PURPLE: FontColor = FontColor::new(0x80, 0x00, 0xff);
254abe3a6eaShanjiezhou 
255abe3a6eaShanjiezhou     pub const fn new(r: u8, g: u8, b: u8) -> Self {
256abe3a6eaShanjiezhou         let val = ((r as u32) << 16) | ((g as u32) << 8) | (b as u32);
257abe3a6eaShanjiezhou         return FontColor(val & 0x00ffffff);
258abe3a6eaShanjiezhou     }
259abe3a6eaShanjiezhou }
260abe3a6eaShanjiezhou 
261abe3a6eaShanjiezhou impl From<u32> for FontColor {
262abe3a6eaShanjiezhou     fn from(value: u32) -> Self {
263abe3a6eaShanjiezhou         return Self(value & 0x00ffffff);
264abe3a6eaShanjiezhou     }
265abe3a6eaShanjiezhou }
266abe3a6eaShanjiezhou impl Into<usize> for FontColor {
267abe3a6eaShanjiezhou     fn into(self) -> usize {
268abe3a6eaShanjiezhou         self.0.clone() as usize
269abe3a6eaShanjiezhou     }
270abe3a6eaShanjiezhou }
271abe3a6eaShanjiezhou impl Into<u32> for FontColor {
272abe3a6eaShanjiezhou     fn into(self) -> u32 {
273abe3a6eaShanjiezhou         self.0.clone()
274abe3a6eaShanjiezhou     }
275abe3a6eaShanjiezhou }
276abe3a6eaShanjiezhou impl Into<u16> for FontColor {
277abe3a6eaShanjiezhou     fn into(self) -> u16 {
278abe3a6eaShanjiezhou         self.0.clone() as u16
279abe3a6eaShanjiezhou     }
280abe3a6eaShanjiezhou }
281abe3a6eaShanjiezhou impl Into<u64> for FontColor {
282abe3a6eaShanjiezhou     fn into(self) -> u64 {
283abe3a6eaShanjiezhou         self.0.clone() as u64
284abe3a6eaShanjiezhou     }
285abe3a6eaShanjiezhou }
286abe3a6eaShanjiezhou 
287abe3a6eaShanjiezhou /// 彩色字符对象
288abe3a6eaShanjiezhou 
289abe3a6eaShanjiezhou #[derive(Clone, Debug, Copy)]
290abe3a6eaShanjiezhou pub struct TextuiCharChromatic {
291abe3a6eaShanjiezhou     c: Option<char>,
292abe3a6eaShanjiezhou 
293abe3a6eaShanjiezhou     // 前景色
294abe3a6eaShanjiezhou     frcolor: FontColor, // rgb
295abe3a6eaShanjiezhou 
296abe3a6eaShanjiezhou     // 背景色
297abe3a6eaShanjiezhou     bkcolor: FontColor, // rgb
298abe3a6eaShanjiezhou }
299abe3a6eaShanjiezhou 
300abe3a6eaShanjiezhou #[derive(Debug)]
3011496ba7bSLoGin pub struct TextuiBuf<'a> {
3021496ba7bSLoGin     buf: Option<&'a mut [u32]>,
3031496ba7bSLoGin     guard: Option<SpinLockGuard<'a, Box<[u32]>>>,
3041496ba7bSLoGin }
305abe3a6eaShanjiezhou 
306abe3a6eaShanjiezhou impl TextuiBuf<'_> {
3071496ba7bSLoGin     pub fn new(buf: &mut ScmBufferInfo) -> TextuiBuf {
3081496ba7bSLoGin         let len = buf.buf_size() / 4;
3091496ba7bSLoGin 
3101496ba7bSLoGin         match &buf.buf {
3111496ba7bSLoGin             ScmBuffer::DeviceBuffer(vaddr) => {
3121496ba7bSLoGin                 return TextuiBuf {
3131496ba7bSLoGin                     buf: Some(unsafe {
3141496ba7bSLoGin                         core::slice::from_raw_parts_mut(vaddr.data() as *mut u32, len)
3151496ba7bSLoGin                     }),
3161496ba7bSLoGin                     guard: None,
3171496ba7bSLoGin                 };
3181496ba7bSLoGin             }
3191496ba7bSLoGin 
3201496ba7bSLoGin             ScmBuffer::DoubleBuffer(double_buffer) => {
3211496ba7bSLoGin                 let guard: SpinLockGuard<'_, Box<[u32]>> = double_buffer.lock();
3221496ba7bSLoGin 
3231496ba7bSLoGin                 return TextuiBuf {
3241496ba7bSLoGin                     buf: None,
3251496ba7bSLoGin                     guard: Some(guard),
3261496ba7bSLoGin                 };
3271496ba7bSLoGin             }
3281496ba7bSLoGin         }
3291496ba7bSLoGin     }
3301496ba7bSLoGin 
3311496ba7bSLoGin     pub fn buf_mut(&mut self) -> &mut [u32] {
3321496ba7bSLoGin         if let Some(buf) = &mut self.buf {
3331496ba7bSLoGin             return buf;
3341496ba7bSLoGin         } else {
3351496ba7bSLoGin             return self.guard.as_mut().unwrap().as_mut();
3361496ba7bSLoGin         }
337abe3a6eaShanjiezhou     }
338abe3a6eaShanjiezhou     pub fn put_color_in_pixel(&mut self, color: u32, index: usize) {
3391496ba7bSLoGin         let buf: &mut [u32] = self.buf_mut();
340abe3a6eaShanjiezhou         buf[index] = color;
341abe3a6eaShanjiezhou     }
342abe3a6eaShanjiezhou     pub fn get_index_of_next_line(now_index: usize) -> usize {
3431496ba7bSLoGin         textui_framework().metadata.read().buf_info().width() as usize + now_index
344abe3a6eaShanjiezhou     }
345abe3a6eaShanjiezhou     pub fn get_index_by_x_y(x: usize, y: usize) -> usize {
3461496ba7bSLoGin         textui_framework().metadata.read().buf_info().width() as usize * y + x
347abe3a6eaShanjiezhou     }
348abe3a6eaShanjiezhou     pub fn get_start_index_by_lineid_lineindex(lineid: LineId, lineindex: LineIndex) -> usize {
349abe3a6eaShanjiezhou         //   x 左上角列像素点位置
350abe3a6eaShanjiezhou         //   y 左上角行像素点位置
351abe3a6eaShanjiezhou         let index_x: u32 = lineindex.into();
352abe3a6eaShanjiezhou         let x: u32 = index_x * TEXTUI_CHAR_WIDTH;
353abe3a6eaShanjiezhou 
354abe3a6eaShanjiezhou         let id_y: u32 = lineid.into();
355abe3a6eaShanjiezhou         let y: u32 = id_y * TEXTUI_CHAR_HEIGHT;
356abe3a6eaShanjiezhou 
357abe3a6eaShanjiezhou         TextuiBuf::get_index_by_x_y(x as usize, y as usize)
358abe3a6eaShanjiezhou     }
359abe3a6eaShanjiezhou }
360abe3a6eaShanjiezhou 
361abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
362abe3a6eaShanjiezhou pub struct Font([u8; 16]);
363abe3a6eaShanjiezhou impl Font {
364abe3a6eaShanjiezhou     #[inline]
365abe3a6eaShanjiezhou     pub fn get_font(character: char) -> Font {
366abe3a6eaShanjiezhou         let x = FONT_8x16.char_map(character);
367abe3a6eaShanjiezhou 
368abe3a6eaShanjiezhou         let mut data = [0u8; 16];
369abe3a6eaShanjiezhou         data.copy_from_slice(x);
370abe3a6eaShanjiezhou         return Font(data);
371abe3a6eaShanjiezhou     }
372abe3a6eaShanjiezhou     pub fn is_frcolor(&self, height: usize, width: usize) -> bool {
373abe3a6eaShanjiezhou         let w = self.0[height];
374abe3a6eaShanjiezhou         let testbit = 1 << (8 - width);
375abe3a6eaShanjiezhou         w & testbit != 0
376abe3a6eaShanjiezhou     }
377abe3a6eaShanjiezhou }
378abe3a6eaShanjiezhou 
379abe3a6eaShanjiezhou impl TextuiCharChromatic {
380abe3a6eaShanjiezhou     pub fn new(c: Option<char>, frcolor: FontColor, bkcolor: FontColor) -> Self {
381abe3a6eaShanjiezhou         TextuiCharChromatic {
382abe3a6eaShanjiezhou             c,
383abe3a6eaShanjiezhou             frcolor,
384abe3a6eaShanjiezhou             bkcolor,
385abe3a6eaShanjiezhou         }
386abe3a6eaShanjiezhou     }
387abe3a6eaShanjiezhou 
388abe3a6eaShanjiezhou     /// 将该字符对象输出到缓冲区
389abe3a6eaShanjiezhou     /// ## 参数
390abe3a6eaShanjiezhou     /// -line_id 要放入的真实行号
391abe3a6eaShanjiezhou     /// -index 要放入的真实列号
392abe3a6eaShanjiezhou     pub fn textui_refresh_character(
393abe3a6eaShanjiezhou         &self,
394abe3a6eaShanjiezhou         lineid: LineId,
395abe3a6eaShanjiezhou         lineindex: LineIndex,
396abe3a6eaShanjiezhou     ) -> Result<i32, SystemError> {
397abe3a6eaShanjiezhou         // 找到要渲染的字符的像素点数据
398abe3a6eaShanjiezhou 
399abe3a6eaShanjiezhou         let font: Font = Font::get_font(self.c.unwrap_or(' '));
400abe3a6eaShanjiezhou 
401abe3a6eaShanjiezhou         let mut count = TextuiBuf::get_start_index_by_lineid_lineindex(lineid, lineindex);
402abe3a6eaShanjiezhou 
4031496ba7bSLoGin         let mut _binding = textui_framework().metadata.read().buf_info();
4041496ba7bSLoGin 
4051496ba7bSLoGin         let mut buf = TextuiBuf::new(&mut _binding);
4061496ba7bSLoGin 
407abe3a6eaShanjiezhou         // 在缓冲区画出一个字体,每个字体有TEXTUI_CHAR_HEIGHT行,TEXTUI_CHAR_WIDTH列个像素点
408abe3a6eaShanjiezhou         for i in 0..TEXTUI_CHAR_HEIGHT {
409abe3a6eaShanjiezhou             let start = count;
410abe3a6eaShanjiezhou             for j in 0..TEXTUI_CHAR_WIDTH {
411abe3a6eaShanjiezhou                 if font.is_frcolor(i as usize, j as usize) {
412abe3a6eaShanjiezhou                     // 字,显示前景色
413abe3a6eaShanjiezhou                     buf.put_color_in_pixel(self.frcolor.into(), count);
414abe3a6eaShanjiezhou                 } else {
415abe3a6eaShanjiezhou                     // 背景色
416abe3a6eaShanjiezhou                     buf.put_color_in_pixel(self.bkcolor.into(), count);
417abe3a6eaShanjiezhou                 }
418abe3a6eaShanjiezhou                 count += 1;
419abe3a6eaShanjiezhou             }
420abe3a6eaShanjiezhou             count = TextuiBuf::get_index_of_next_line(start);
421abe3a6eaShanjiezhou         }
422abe3a6eaShanjiezhou 
423abe3a6eaShanjiezhou         return Ok(0);
424abe3a6eaShanjiezhou     }
425abe3a6eaShanjiezhou 
426abe3a6eaShanjiezhou     pub fn no_init_textui_render_chromatic(&self, lineid: LineId, lineindex: LineIndex) {
427abe3a6eaShanjiezhou         // 找到要渲染的字符的像素点数据
428abe3a6eaShanjiezhou         let font = Font::get_font(self.c.unwrap_or(' '));
429abe3a6eaShanjiezhou 
430abe3a6eaShanjiezhou         //   x 左上角列像素点位置
431abe3a6eaShanjiezhou         //   y 左上角行像素点位置
432abe3a6eaShanjiezhou         let index_x: u32 = lineindex.into();
433abe3a6eaShanjiezhou         let x: u32 = index_x * TEXTUI_CHAR_WIDTH;
434abe3a6eaShanjiezhou 
435abe3a6eaShanjiezhou         let id_y: u32 = lineid.into();
436abe3a6eaShanjiezhou         let y: u32 = id_y * TEXTUI_CHAR_HEIGHT;
4371496ba7bSLoGin 
4381496ba7bSLoGin         let buf_width = video_refresh_manager().device_buffer().width();
439abe3a6eaShanjiezhou         // 找到输入缓冲区的起始地址位置
4401496ba7bSLoGin         let buf_start =
4411496ba7bSLoGin             if let ScmBuffer::DeviceBuffer(vaddr) = video_refresh_manager().device_buffer().buf {
4421496ba7bSLoGin                 vaddr
4431496ba7bSLoGin             } else {
4441496ba7bSLoGin                 panic!("device buffer is not init");
4451496ba7bSLoGin             };
446abe3a6eaShanjiezhou 
447abe3a6eaShanjiezhou         let mut testbit: u32; // 用来测试特定行的某列是背景还是字体本身
448abe3a6eaShanjiezhou 
449abe3a6eaShanjiezhou         // 在缓冲区画出一个字体,每个字体有TEXTUI_CHAR_HEIGHT行,TEXTUI_CHAR_WIDTH列个像素点
450abe3a6eaShanjiezhou         for i in 0..TEXTUI_CHAR_HEIGHT {
451abe3a6eaShanjiezhou             // 计算出帧缓冲区每一行打印的起始位置的地址(起始位置+(y+i)*缓冲区的宽度+x)
452abe3a6eaShanjiezhou 
4531496ba7bSLoGin             let mut addr: *mut u32 =
4541496ba7bSLoGin                 (buf_start + buf_width as usize * 4 * (y as usize + i as usize) + 4 * x as usize)
4551496ba7bSLoGin                     .data() as *mut u32;
456abe3a6eaShanjiezhou 
457abe3a6eaShanjiezhou             testbit = 1 << (TEXTUI_CHAR_WIDTH + 1);
458abe3a6eaShanjiezhou 
459abe3a6eaShanjiezhou             for _j in 0..TEXTUI_CHAR_WIDTH {
460abe3a6eaShanjiezhou                 //从左往右逐个测试相应位
461abe3a6eaShanjiezhou                 testbit >>= 1;
462abe3a6eaShanjiezhou                 if (font.0[i as usize] & testbit as u8) != 0 {
463abe3a6eaShanjiezhou                     unsafe { *addr = self.frcolor.into() }; // 字,显示前景色
464abe3a6eaShanjiezhou                 } else {
465abe3a6eaShanjiezhou                     unsafe { *addr = self.bkcolor.into() }; // 背景色
466abe3a6eaShanjiezhou                 }
467abe3a6eaShanjiezhou 
468abe3a6eaShanjiezhou                 unsafe {
469abe3a6eaShanjiezhou                     addr = (addr.offset(1)) as *mut u32;
470abe3a6eaShanjiezhou                 }
471abe3a6eaShanjiezhou             }
472abe3a6eaShanjiezhou         }
473abe3a6eaShanjiezhou     }
474abe3a6eaShanjiezhou }
475abe3a6eaShanjiezhou 
476abe3a6eaShanjiezhou /// 单色显示的虚拟行结构体
477abe3a6eaShanjiezhou 
478abe3a6eaShanjiezhou #[derive(Clone, Debug, Default)]
479abe3a6eaShanjiezhou pub struct TextuiVlineNormal {
480abe3a6eaShanjiezhou     _characters: Vec<TextuiCharNormal>, // 字符对象数组
481abe3a6eaShanjiezhou     _index: i16,                        // 当前操作的位置
482abe3a6eaShanjiezhou }
483abe3a6eaShanjiezhou /// 彩色显示的虚拟行结构体
484abe3a6eaShanjiezhou 
485abe3a6eaShanjiezhou #[derive(Clone, Debug, Default)]
486abe3a6eaShanjiezhou pub struct TextuiVlineChromatic {
487abe3a6eaShanjiezhou     chars: Vec<TextuiCharChromatic>, // 字符对象数组
488abe3a6eaShanjiezhou     index: LineIndex,                // 当前操作的位置
489abe3a6eaShanjiezhou }
490abe3a6eaShanjiezhou impl TextuiVlineChromatic {
491abe3a6eaShanjiezhou     pub fn new(char_num: usize) -> Self {
492abe3a6eaShanjiezhou         let mut r = TextuiVlineChromatic {
493abe3a6eaShanjiezhou             chars: Vec::with_capacity(char_num),
494abe3a6eaShanjiezhou             index: LineIndex::new(0),
495abe3a6eaShanjiezhou         };
496abe3a6eaShanjiezhou 
497abe3a6eaShanjiezhou         for _ in 0..char_num {
498abe3a6eaShanjiezhou             r.chars.push(TextuiCharChromatic::new(
499abe3a6eaShanjiezhou                 None,
500abe3a6eaShanjiezhou                 FontColor::BLACK,
501abe3a6eaShanjiezhou                 FontColor::BLACK,
502abe3a6eaShanjiezhou             ));
503abe3a6eaShanjiezhou         }
504abe3a6eaShanjiezhou 
505abe3a6eaShanjiezhou         return r;
506abe3a6eaShanjiezhou     }
507abe3a6eaShanjiezhou }
508abe3a6eaShanjiezhou 
509abe3a6eaShanjiezhou #[derive(Clone, Debug)]
510abe3a6eaShanjiezhou pub enum TextuiVline {
511abe3a6eaShanjiezhou     Chromatic(TextuiVlineChromatic),
512abe3a6eaShanjiezhou     _Normal(TextuiVlineNormal),
513abe3a6eaShanjiezhou }
514abe3a6eaShanjiezhou 
515abe3a6eaShanjiezhou #[derive(Debug, Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
516abe3a6eaShanjiezhou pub struct WindowId(u32);
517abe3a6eaShanjiezhou 
518abe3a6eaShanjiezhou impl WindowId {
519abe3a6eaShanjiezhou     pub fn new() -> Self {
520abe3a6eaShanjiezhou         static MAX_ID: AtomicU32 = AtomicU32::new(0);
521abe3a6eaShanjiezhou         return WindowId(MAX_ID.fetch_add(1, Ordering::SeqCst));
522abe3a6eaShanjiezhou     }
523abe3a6eaShanjiezhou }
524abe3a6eaShanjiezhou #[allow(dead_code)]
525abe3a6eaShanjiezhou #[derive(Clone, Debug)]
526abe3a6eaShanjiezhou pub struct TextuiWindow {
527abe3a6eaShanjiezhou     // 虚拟行是个循环表,头和尾相接
528abe3a6eaShanjiezhou     id: WindowId,
529abe3a6eaShanjiezhou     // 虚拟行总数
530abe3a6eaShanjiezhou     vline_sum: i32,
531abe3a6eaShanjiezhou     // 当前已经使用了的虚拟行总数(即在已经输入到缓冲区(之后显示在屏幕上)的虚拟行数量)
532abe3a6eaShanjiezhou     vlines_used: i32,
533abe3a6eaShanjiezhou     // 位于最顶上的那一个虚拟行的行号
534abe3a6eaShanjiezhou     top_vline: LineId,
535abe3a6eaShanjiezhou     // 储存虚拟行的数组
536abe3a6eaShanjiezhou     vlines: Vec<TextuiVline>,
537abe3a6eaShanjiezhou     // 正在操作的vline
538abe3a6eaShanjiezhou     vline_operating: LineId,
539abe3a6eaShanjiezhou     // 每行最大容纳的字符数
540abe3a6eaShanjiezhou     chars_per_line: i32,
541abe3a6eaShanjiezhou     // 窗口flag
542abe3a6eaShanjiezhou     flags: WindowFlag,
543abe3a6eaShanjiezhou }
544abe3a6eaShanjiezhou 
545abe3a6eaShanjiezhou impl TextuiWindow {
546abe3a6eaShanjiezhou     /// 使用参数初始化window对象
547abe3a6eaShanjiezhou     /// ## 参数
548abe3a6eaShanjiezhou     ///
549abe3a6eaShanjiezhou     /// -flags 标志位
550abe3a6eaShanjiezhou     /// -vlines_num 虚拟行的总数
551abe3a6eaShanjiezhou     /// -chars_num 每行最大的字符数
552abe3a6eaShanjiezhou 
553abe3a6eaShanjiezhou     pub fn new(flags: WindowFlag, vlines_num: i32, chars_num: i32) -> Self {
554abe3a6eaShanjiezhou         let mut initial_vlines = Vec::new();
555abe3a6eaShanjiezhou 
556abe3a6eaShanjiezhou         for _ in 0..vlines_num {
557abe3a6eaShanjiezhou             let vline = TextuiVlineChromatic::new(chars_num as usize);
558abe3a6eaShanjiezhou 
559abe3a6eaShanjiezhou             initial_vlines.push(TextuiVline::Chromatic(vline));
560abe3a6eaShanjiezhou         }
561abe3a6eaShanjiezhou         TextuiWindow {
562abe3a6eaShanjiezhou             id: WindowId::new(),
563abe3a6eaShanjiezhou             flags,
564abe3a6eaShanjiezhou             vline_sum: vlines_num,
565abe3a6eaShanjiezhou             vlines_used: 1,
566abe3a6eaShanjiezhou             top_vline: LineId::new(0),
567abe3a6eaShanjiezhou             vlines: initial_vlines,
568abe3a6eaShanjiezhou             vline_operating: LineId::new(0),
569abe3a6eaShanjiezhou             chars_per_line: chars_num,
570abe3a6eaShanjiezhou         }
571abe3a6eaShanjiezhou     }
572abe3a6eaShanjiezhou 
573abe3a6eaShanjiezhou     /// 刷新某个窗口的缓冲区的某个虚拟行的连续n个字符对象
574abe3a6eaShanjiezhou     /// ## 参数
575abe3a6eaShanjiezhou     /// - window 窗口结构体
576abe3a6eaShanjiezhou     /// - vline_id 要刷新的虚拟行号
577abe3a6eaShanjiezhou     /// - start 起始字符号
578abe3a6eaShanjiezhou     /// - count 要刷新的字符数量
579abe3a6eaShanjiezhou 
580abe3a6eaShanjiezhou     fn textui_refresh_characters(
581abe3a6eaShanjiezhou         &mut self,
582abe3a6eaShanjiezhou         vline_id: LineId,
583abe3a6eaShanjiezhou         start: LineIndex,
584abe3a6eaShanjiezhou         count: i32,
585abe3a6eaShanjiezhou     ) -> Result<(), SystemError> {
586abe3a6eaShanjiezhou         let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst);
587abe3a6eaShanjiezhou 
588abe3a6eaShanjiezhou         // 判断虚拟行参数是否合法
589abe3a6eaShanjiezhou         if unlikely(
590abe3a6eaShanjiezhou             !vline_id.check(self.vline_sum)
591abe3a6eaShanjiezhou                 || (<LineIndex as Into<i32>>::into(start) + count) > self.chars_per_line,
592abe3a6eaShanjiezhou         ) {
593abe3a6eaShanjiezhou             return Err(SystemError::EINVAL);
594abe3a6eaShanjiezhou         }
595abe3a6eaShanjiezhou         // 计算虚拟行对应的真实行(即要渲染的行)
596abe3a6eaShanjiezhou         let mut actual_line_id = vline_id - self.top_vline; //为正说明虚拟行不在真实行显示的区域上面
597abe3a6eaShanjiezhou 
598abe3a6eaShanjiezhou         if <LineId as Into<i32>>::into(actual_line_id) < 0 {
599abe3a6eaShanjiezhou             //真实行数小于虚拟行数,则需要加上真实行数的位置,以便正确计算真实行
600abe3a6eaShanjiezhou             actual_line_id = actual_line_id + actual_line_sum;
601abe3a6eaShanjiezhou         }
602abe3a6eaShanjiezhou 
603abe3a6eaShanjiezhou         // 将此窗口的某个虚拟行的连续n个字符对象往缓存区写入
604abe3a6eaShanjiezhou         if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) {
605abe3a6eaShanjiezhou             let vline = &mut self.vlines[<LineId as Into<usize>>::into(vline_id)];
606abe3a6eaShanjiezhou             let mut i = 0;
607abe3a6eaShanjiezhou             let mut index = start;
608abe3a6eaShanjiezhou 
609abe3a6eaShanjiezhou             while i < count {
610abe3a6eaShanjiezhou                 if let TextuiVline::Chromatic(vline) = vline {
611abe3a6eaShanjiezhou                     vline.chars[<LineIndex as Into<usize>>::into(index)]
612abe3a6eaShanjiezhou                         .textui_refresh_character(actual_line_id, index)?;
613abe3a6eaShanjiezhou 
614abe3a6eaShanjiezhou                     index = index + 1;
615abe3a6eaShanjiezhou                 }
616abe3a6eaShanjiezhou                 i += 1;
617abe3a6eaShanjiezhou             }
618abe3a6eaShanjiezhou         }
619abe3a6eaShanjiezhou 
620abe3a6eaShanjiezhou         return Ok(());
621abe3a6eaShanjiezhou     }
622abe3a6eaShanjiezhou 
623abe3a6eaShanjiezhou     /// 重新渲染某个窗口的某个虚拟行
624abe3a6eaShanjiezhou     /// ## 参数
625abe3a6eaShanjiezhou 
626abe3a6eaShanjiezhou     /// - window 窗口结构体
627abe3a6eaShanjiezhou     /// - vline_id 虚拟行号
628abe3a6eaShanjiezhou 
629abe3a6eaShanjiezhou     fn textui_refresh_vline(&mut self, vline_id: LineId) -> Result<(), SystemError> {
630abe3a6eaShanjiezhou         if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) {
631abe3a6eaShanjiezhou             return self.textui_refresh_characters(
632abe3a6eaShanjiezhou                 vline_id,
633abe3a6eaShanjiezhou                 LineIndex::new(0),
634abe3a6eaShanjiezhou                 self.chars_per_line,
635abe3a6eaShanjiezhou             );
636abe3a6eaShanjiezhou         } else {
637abe3a6eaShanjiezhou             //todo支持纯文本字符()
638abe3a6eaShanjiezhou             todo!();
639abe3a6eaShanjiezhou         }
640abe3a6eaShanjiezhou     }
641abe3a6eaShanjiezhou 
642abe3a6eaShanjiezhou     // 刷新某个窗口的start 到start + count行(即将这些行输入到缓冲区)
643abe3a6eaShanjiezhou     fn textui_refresh_vlines(&mut self, start: LineId, count: i32) -> Result<i32, SystemError> {
644abe3a6eaShanjiezhou         let mut refresh_count = count;
645abe3a6eaShanjiezhou         for i in <LineId as Into<i32>>::into(start)
646abe3a6eaShanjiezhou             ..(self.vline_sum).min(<LineId as Into<i32>>::into(start) + count)
647abe3a6eaShanjiezhou         {
648abe3a6eaShanjiezhou             self.textui_refresh_vline(LineId::new(i))?;
649abe3a6eaShanjiezhou             refresh_count -= 1;
650abe3a6eaShanjiezhou         }
651abe3a6eaShanjiezhou         //因为虚拟行是循环表
652abe3a6eaShanjiezhou         let mut refresh_start = 0;
653abe3a6eaShanjiezhou         while refresh_count > 0 {
654abe3a6eaShanjiezhou             self.textui_refresh_vline(LineId::new(refresh_start))?;
655abe3a6eaShanjiezhou             refresh_start += 1;
656abe3a6eaShanjiezhou             refresh_count -= 1;
657abe3a6eaShanjiezhou         }
658abe3a6eaShanjiezhou         return Ok(0);
659abe3a6eaShanjiezhou     }
660abe3a6eaShanjiezhou 
661abe3a6eaShanjiezhou     /// 往某个窗口的缓冲区的某个虚拟行插入换行
662abe3a6eaShanjiezhou     /// ## 参数
663abe3a6eaShanjiezhou     /// - window 窗口结构体
664abe3a6eaShanjiezhou     /// - vline_id 虚拟行号
665abe3a6eaShanjiezhou 
666abe3a6eaShanjiezhou     fn textui_new_line(&mut self) -> Result<i32, SystemError> {
667abe3a6eaShanjiezhou         // todo: 支持在两个虚拟行之间插入一个新行
668abe3a6eaShanjiezhou         let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst);
669abe3a6eaShanjiezhou         self.vline_operating = self.vline_operating + 1;
670abe3a6eaShanjiezhou         //如果已经到了最大行数,则重新从0开始
671abe3a6eaShanjiezhou         if !self.vline_operating.check(self.vline_sum) {
672abe3a6eaShanjiezhou             self.vline_operating = LineId::new(0);
673abe3a6eaShanjiezhou         }
674abe3a6eaShanjiezhou 
675abe3a6eaShanjiezhou         if let TextuiVline::Chromatic(vline) =
676abe3a6eaShanjiezhou             &mut (self.vlines[<LineId as Into<usize>>::into(self.vline_operating)])
677abe3a6eaShanjiezhou         {
678abe3a6eaShanjiezhou             for i in 0..self.chars_per_line {
679abe3a6eaShanjiezhou                 if let Some(v_char) = vline.chars.get_mut(i as usize) {
680abe3a6eaShanjiezhou                     v_char.c = None;
681abe3a6eaShanjiezhou                     v_char.frcolor = FontColor::BLACK;
682abe3a6eaShanjiezhou                     v_char.bkcolor = FontColor::BLACK;
683abe3a6eaShanjiezhou                 }
684abe3a6eaShanjiezhou             }
685abe3a6eaShanjiezhou             vline.index = LineIndex::new(0);
686abe3a6eaShanjiezhou         }
687abe3a6eaShanjiezhou         // 当已经使用的虚拟行总数等于真实行总数时,说明窗口中已经显示的文本行数已经达到了窗口的最大容量。这时,如果继续在窗口中添加新的文本,就会导致文本溢出窗口而无法显示。因此,需要往下滚动屏幕来显示更多的文本。
688abe3a6eaShanjiezhou 
689abe3a6eaShanjiezhou         if self.vlines_used == actual_line_sum {
690abe3a6eaShanjiezhou             self.top_vline = self.top_vline + 1;
691abe3a6eaShanjiezhou 
692abe3a6eaShanjiezhou             if !self.top_vline.check(self.vline_sum) {
693abe3a6eaShanjiezhou                 self.top_vline = LineId::new(0);
694abe3a6eaShanjiezhou             }
695abe3a6eaShanjiezhou 
696abe3a6eaShanjiezhou             // 刷新所有行
697abe3a6eaShanjiezhou             self.textui_refresh_vlines(self.top_vline, actual_line_sum)?;
698abe3a6eaShanjiezhou         } else {
699abe3a6eaShanjiezhou             //换行说明上一行已经在缓冲区中,所以已经使用的虚拟行总数+1
700abe3a6eaShanjiezhou             self.vlines_used += 1;
701abe3a6eaShanjiezhou         }
702abe3a6eaShanjiezhou 
703abe3a6eaShanjiezhou         return Ok(0);
704abe3a6eaShanjiezhou     }
705abe3a6eaShanjiezhou 
706abe3a6eaShanjiezhou     /// 真正向窗口的缓冲区上输入字符的函数(位置为window.vline_operating,window.vline_operating.index)
707abe3a6eaShanjiezhou     /// ## 参数
708abe3a6eaShanjiezhou     /// - window
709abe3a6eaShanjiezhou     /// - character
710abe3a6eaShanjiezhou 
711abe3a6eaShanjiezhou     fn true_textui_putchar_window(
712abe3a6eaShanjiezhou         &mut self,
713abe3a6eaShanjiezhou         character: char,
714abe3a6eaShanjiezhou         frcolor: FontColor,
715abe3a6eaShanjiezhou         bkcolor: FontColor,
716abe3a6eaShanjiezhou     ) -> Result<(), SystemError> {
717abe3a6eaShanjiezhou         // 启用彩色字符
718abe3a6eaShanjiezhou         if self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) {
719abe3a6eaShanjiezhou             let mut line_index = LineIndex::new(0); //操作的列号
720abe3a6eaShanjiezhou             if let TextuiVline::Chromatic(vline) =
721abe3a6eaShanjiezhou                 &mut (self.vlines[<LineId as Into<usize>>::into(self.vline_operating)])
722abe3a6eaShanjiezhou             {
723abe3a6eaShanjiezhou                 let index = <LineIndex as Into<usize>>::into(vline.index);
724abe3a6eaShanjiezhou 
725abe3a6eaShanjiezhou                 if let Some(v_char) = vline.chars.get_mut(index) {
726abe3a6eaShanjiezhou                     v_char.c = Some(character);
727abe3a6eaShanjiezhou                     v_char.frcolor = frcolor;
728abe3a6eaShanjiezhou                     v_char.bkcolor = bkcolor;
729abe3a6eaShanjiezhou                 }
730abe3a6eaShanjiezhou                 line_index = vline.index;
731abe3a6eaShanjiezhou                 vline.index = vline.index + 1;
732abe3a6eaShanjiezhou             }
733abe3a6eaShanjiezhou 
734abe3a6eaShanjiezhou             self.textui_refresh_characters(self.vline_operating, line_index, 1)?;
735abe3a6eaShanjiezhou 
736abe3a6eaShanjiezhou             // 加入光标后,因为会识别光标,所以需超过该行最大字符数才能创建新行
737abe3a6eaShanjiezhou             if !line_index.check(self.chars_per_line - 1) {
738abe3a6eaShanjiezhou                 self.textui_new_line()?;
739abe3a6eaShanjiezhou             }
740abe3a6eaShanjiezhou         } else {
741abe3a6eaShanjiezhou             // todo: 支持纯文本字符
742abe3a6eaShanjiezhou             todo!();
743abe3a6eaShanjiezhou         }
744abe3a6eaShanjiezhou         return Ok(());
745abe3a6eaShanjiezhou     }
746abe3a6eaShanjiezhou     /// 根据输入的一个字符在窗口上输出
747abe3a6eaShanjiezhou     /// ## 参数
748abe3a6eaShanjiezhou 
749abe3a6eaShanjiezhou     /// - window 窗口
750abe3a6eaShanjiezhou     /// - character 字符
751abe3a6eaShanjiezhou     /// - FRcolor 前景色(RGB)
752abe3a6eaShanjiezhou     /// - BKcolor 背景色(RGB)
753abe3a6eaShanjiezhou 
754abe3a6eaShanjiezhou     fn textui_putchar_window(
755abe3a6eaShanjiezhou         &mut self,
756abe3a6eaShanjiezhou         character: char,
757abe3a6eaShanjiezhou         frcolor: FontColor,
758abe3a6eaShanjiezhou         bkcolor: FontColor,
759abe3a6eaShanjiezhou         is_enable_window: bool,
760abe3a6eaShanjiezhou     ) -> Result<(), SystemError> {
761abe3a6eaShanjiezhou         let actual_line_sum = textui_framework().actual_line.load(Ordering::SeqCst);
762abe3a6eaShanjiezhou 
763abe3a6eaShanjiezhou         //字符'\0'代表ASCII码表中的空字符,表示字符串的结尾
764abe3a6eaShanjiezhou         if unlikely(character == '\0') {
765abe3a6eaShanjiezhou             return Ok(());
766abe3a6eaShanjiezhou         }
767abe3a6eaShanjiezhou 
768abe3a6eaShanjiezhou         if unlikely(character == '\r') {
769abe3a6eaShanjiezhou             return Ok(());
770abe3a6eaShanjiezhou         }
771abe3a6eaShanjiezhou 
772abe3a6eaShanjiezhou         // 暂不支持纯文本窗口
773abe3a6eaShanjiezhou         if !self.flags.contains(WindowFlag::TEXTUI_CHROMATIC) {
774abe3a6eaShanjiezhou             return Ok(());
775abe3a6eaShanjiezhou         }
776a0c98cd4SJomo         send_to_default_serial8250_port(&[character as u8]);
777abe3a6eaShanjiezhou 
778abe3a6eaShanjiezhou         //进行换行操作
779abe3a6eaShanjiezhou         if character == '\n' {
780abe3a6eaShanjiezhou             // 换行时还需要输出\r
781a03c4f9dSLoGin             send_to_default_serial8250_port(&[b'\r']);
782abe3a6eaShanjiezhou             if is_enable_window == true {
783abe3a6eaShanjiezhou                 self.textui_new_line()?;
784abe3a6eaShanjiezhou             }
785abe3a6eaShanjiezhou             return Ok(());
786abe3a6eaShanjiezhou         }
787abe3a6eaShanjiezhou         // 输出制表符
788abe3a6eaShanjiezhou         else if character == '\t' {
789abe3a6eaShanjiezhou             if is_enable_window == true {
790abe3a6eaShanjiezhou                 if let TextuiVline::Chromatic(vline) =
791abe3a6eaShanjiezhou                     &self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]
792abe3a6eaShanjiezhou                 {
793abe3a6eaShanjiezhou                     //打印的空格数(注意将每行分成一个个表格,每个表格为8个字符)
794abe3a6eaShanjiezhou                     let mut space_to_print = 8 - <LineIndex as Into<usize>>::into(vline.index) % 8;
795abe3a6eaShanjiezhou                     while space_to_print > 0 {
796abe3a6eaShanjiezhou                         self.true_textui_putchar_window(' ', frcolor, bkcolor)?;
797abe3a6eaShanjiezhou                         space_to_print -= 1;
798abe3a6eaShanjiezhou                     }
799abe3a6eaShanjiezhou                 }
800abe3a6eaShanjiezhou             }
801abe3a6eaShanjiezhou         }
802abe3a6eaShanjiezhou         // 字符 '\x08' 代表 ASCII 码中的退格字符。它在输出中的作用是将光标向左移动一个位置,并在该位置上输出后续的字符,从而实现字符的删除或替换。
803abe3a6eaShanjiezhou         else if character == '\x08' {
804abe3a6eaShanjiezhou             if is_enable_window == true {
805abe3a6eaShanjiezhou                 let mut tmp = LineIndex(0);
806abe3a6eaShanjiezhou                 if let TextuiVline::Chromatic(vline) =
807abe3a6eaShanjiezhou                     &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]
808abe3a6eaShanjiezhou                 {
809abe3a6eaShanjiezhou                     vline.index = vline.index - 1;
810abe3a6eaShanjiezhou                     tmp = vline.index;
811abe3a6eaShanjiezhou                 }
812abe3a6eaShanjiezhou                 if <LineIndex as Into<i32>>::into(tmp) >= 0 {
813abe3a6eaShanjiezhou                     if let TextuiVline::Chromatic(vline) =
814abe3a6eaShanjiezhou                         &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]
815abe3a6eaShanjiezhou                     {
816abe3a6eaShanjiezhou                         if let Some(v_char) =
817abe3a6eaShanjiezhou                             vline.chars.get_mut(<LineIndex as Into<usize>>::into(tmp))
818abe3a6eaShanjiezhou                         {
819abe3a6eaShanjiezhou                             v_char.c = Some(' ');
820abe3a6eaShanjiezhou 
821abe3a6eaShanjiezhou                             v_char.bkcolor = bkcolor;
822abe3a6eaShanjiezhou                         }
823abe3a6eaShanjiezhou                     }
824abe3a6eaShanjiezhou                     return self.textui_refresh_characters(self.vline_operating, tmp, 1);
825abe3a6eaShanjiezhou                 }
826abe3a6eaShanjiezhou                 // 需要向上缩一行
827abe3a6eaShanjiezhou                 if <LineIndex as Into<i32>>::into(tmp) < 0 {
828abe3a6eaShanjiezhou                     // 当前行为空,需要重新刷新
829abe3a6eaShanjiezhou                     if let TextuiVline::Chromatic(vline) =
830abe3a6eaShanjiezhou                         &mut self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]
831abe3a6eaShanjiezhou                     {
832abe3a6eaShanjiezhou                         vline.index = LineIndex::new(0);
833abe3a6eaShanjiezhou                         for i in 0..self.chars_per_line {
834abe3a6eaShanjiezhou                             if let Some(v_char) = vline.chars.get_mut(i as usize) {
835abe3a6eaShanjiezhou                                 v_char.c = None;
836abe3a6eaShanjiezhou                                 v_char.frcolor = FontColor::BLACK;
837abe3a6eaShanjiezhou                                 v_char.bkcolor = FontColor::BLACK;
838abe3a6eaShanjiezhou                             }
839abe3a6eaShanjiezhou                         }
840abe3a6eaShanjiezhou                     }
841abe3a6eaShanjiezhou                     // 上缩一行
842abe3a6eaShanjiezhou                     self.vline_operating = self.vline_operating - 1;
843abe3a6eaShanjiezhou                     if self.vline_operating.data() < 0 {
844abe3a6eaShanjiezhou                         self.vline_operating = LineId(self.vline_sum - 1);
845abe3a6eaShanjiezhou                     }
846abe3a6eaShanjiezhou 
847abe3a6eaShanjiezhou                     // 考虑是否向上滚动(在top_vline上退格)
848abe3a6eaShanjiezhou                     if self.vlines_used > actual_line_sum {
849abe3a6eaShanjiezhou                         self.top_vline = self.top_vline - 1;
850abe3a6eaShanjiezhou                         if <LineId as Into<i32>>::into(self.top_vline) < 0 {
851abe3a6eaShanjiezhou                             self.top_vline = LineId(self.vline_sum - 1);
852abe3a6eaShanjiezhou                         }
853abe3a6eaShanjiezhou                     }
854abe3a6eaShanjiezhou                     //因为上缩一行所以显示在屏幕中的虚拟行少一
855abe3a6eaShanjiezhou                     self.vlines_used -= 1;
856abe3a6eaShanjiezhou                     self.textui_refresh_vlines(self.top_vline, actual_line_sum)?;
857abe3a6eaShanjiezhou                 }
858abe3a6eaShanjiezhou             }
859abe3a6eaShanjiezhou         } else {
860abe3a6eaShanjiezhou             if is_enable_window == true {
861abe3a6eaShanjiezhou                 if let TextuiVline::Chromatic(vline) =
862abe3a6eaShanjiezhou                     &self.vlines[<LineId as Into<usize>>::into(self.vline_operating)]
863abe3a6eaShanjiezhou                 {
864abe3a6eaShanjiezhou                     if !vline.index.check(self.chars_per_line) {
865abe3a6eaShanjiezhou                         self.textui_new_line()?;
866abe3a6eaShanjiezhou                     }
867abe3a6eaShanjiezhou 
868abe3a6eaShanjiezhou                     return self.true_textui_putchar_window(character, frcolor, bkcolor);
869abe3a6eaShanjiezhou                 }
870abe3a6eaShanjiezhou             }
871abe3a6eaShanjiezhou         }
872abe3a6eaShanjiezhou 
873abe3a6eaShanjiezhou         return Ok(());
874abe3a6eaShanjiezhou     }
875abe3a6eaShanjiezhou }
876abe3a6eaShanjiezhou impl Default for TextuiWindow {
877abe3a6eaShanjiezhou     fn default() -> Self {
878abe3a6eaShanjiezhou         TextuiWindow {
879abe3a6eaShanjiezhou             id: WindowId(0),
880abe3a6eaShanjiezhou             flags: WindowFlag::TEXTUI_CHROMATIC,
881abe3a6eaShanjiezhou             vline_sum: 0,
882abe3a6eaShanjiezhou             vlines_used: 1,
883abe3a6eaShanjiezhou             top_vline: LineId::new(0),
884abe3a6eaShanjiezhou             vlines: Vec::new(),
885abe3a6eaShanjiezhou             vline_operating: LineId::new(0),
886abe3a6eaShanjiezhou             chars_per_line: 0,
887abe3a6eaShanjiezhou         }
888abe3a6eaShanjiezhou     }
889abe3a6eaShanjiezhou }
890abe3a6eaShanjiezhou #[allow(dead_code)]
891abe3a6eaShanjiezhou #[derive(Debug)]
892abe3a6eaShanjiezhou pub struct TextUiFramework {
8931496ba7bSLoGin     metadata: RwLock<ScmUiFrameworkMetadata>,
894abe3a6eaShanjiezhou     window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>>,
895abe3a6eaShanjiezhou     actual_line: AtomicI32, // 真实行的数量(textui的帧缓冲区能容纳的内容的行数)
896abe3a6eaShanjiezhou     current_window: Arc<SpinLock<TextuiWindow>>, // 当前的主窗口
897abe3a6eaShanjiezhou     default_window: Arc<SpinLock<TextuiWindow>>, // 默认print到的窗口
898abe3a6eaShanjiezhou }
899abe3a6eaShanjiezhou 
900abe3a6eaShanjiezhou impl TextUiFramework {
901abe3a6eaShanjiezhou     pub fn new(
902abe3a6eaShanjiezhou         metadata: ScmUiFrameworkMetadata,
903abe3a6eaShanjiezhou         window_list: Arc<SpinLock<LinkedList<Arc<SpinLock<TextuiWindow>>>>>,
904abe3a6eaShanjiezhou         current_window: Arc<SpinLock<TextuiWindow>>,
905abe3a6eaShanjiezhou         default_window: Arc<SpinLock<TextuiWindow>>,
906abe3a6eaShanjiezhou     ) -> Self {
907abe3a6eaShanjiezhou         let actual_line =
9081496ba7bSLoGin             AtomicI32::new((&metadata.buf_info().height() / TEXTUI_CHAR_HEIGHT) as i32);
909abe3a6eaShanjiezhou         let inner = TextUiFramework {
9101496ba7bSLoGin             metadata: RwLock::new(metadata),
911abe3a6eaShanjiezhou             window_list,
912abe3a6eaShanjiezhou             actual_line,
913abe3a6eaShanjiezhou             current_window,
914abe3a6eaShanjiezhou             default_window,
915abe3a6eaShanjiezhou         };
916abe3a6eaShanjiezhou         return inner;
917abe3a6eaShanjiezhou     }
918abe3a6eaShanjiezhou }
919abe3a6eaShanjiezhou 
9201496ba7bSLoGin impl ScmUiFramework for TextUiFramework {
921abe3a6eaShanjiezhou     // 安装ui框架的回调函数
922abe3a6eaShanjiezhou     fn install(&self) -> Result<i32, SystemError> {
923a03c4f9dSLoGin         send_to_default_serial8250_port("\ntextui_install_handler\n\0".as_bytes());
924abe3a6eaShanjiezhou         return Ok(0);
925abe3a6eaShanjiezhou     }
926abe3a6eaShanjiezhou     // 卸载ui框架的回调函数
927abe3a6eaShanjiezhou     fn uninstall(&self) -> Result<i32, SystemError> {
928abe3a6eaShanjiezhou         return Ok(0);
929abe3a6eaShanjiezhou     }
930abe3a6eaShanjiezhou     // 启用ui框架的回调函数
931abe3a6eaShanjiezhou     fn enable(&self) -> Result<i32, SystemError> {
9321a72a751SLoGin         textui_enable_put_to_window();
933abe3a6eaShanjiezhou         return Ok(0);
934abe3a6eaShanjiezhou     }
935abe3a6eaShanjiezhou     // 禁用ui框架的回调函数
936abe3a6eaShanjiezhou     fn disable(&self) -> Result<i32, SystemError> {
9371a72a751SLoGin         textui_disable_put_to_window();
938abe3a6eaShanjiezhou 
939abe3a6eaShanjiezhou         return Ok(0);
940abe3a6eaShanjiezhou     }
941abe3a6eaShanjiezhou     // 改变ui框架的帧缓冲区的回调函数
942abe3a6eaShanjiezhou     fn change(&self, buf_info: ScmBufferInfo) -> Result<i32, SystemError> {
9431496ba7bSLoGin         let old_buf = textui_framework().metadata.read().buf_info();
9441496ba7bSLoGin 
9451496ba7bSLoGin         textui_framework().metadata.write().set_buf_info(buf_info);
9461496ba7bSLoGin 
9471496ba7bSLoGin         let mut new_buf = textui_framework().metadata.read().buf_info();
9481496ba7bSLoGin 
9491496ba7bSLoGin         new_buf.copy_from_nonoverlapping(&old_buf);
9501496ba7bSLoGin         kdebug!("textui change buf_info: old: {:?}", old_buf);
9511496ba7bSLoGin         kdebug!("textui change buf_info: new: {:?}", new_buf);
9521496ba7bSLoGin 
953abe3a6eaShanjiezhou         return Ok(0);
954abe3a6eaShanjiezhou     }
955abe3a6eaShanjiezhou     ///  获取ScmUiFramework的元数据
956abe3a6eaShanjiezhou     ///  ## 返回值
957abe3a6eaShanjiezhou     ///
958abe3a6eaShanjiezhou     ///  -成功:Ok(ScmUiFramework的元数据)
959abe3a6eaShanjiezhou     ///  -失败:Err(错误码)
960abe3a6eaShanjiezhou     fn metadata(&self) -> Result<ScmUiFrameworkMetadata, SystemError> {
9611496ba7bSLoGin         let metadata = self.metadata.read().clone();
962abe3a6eaShanjiezhou 
963abe3a6eaShanjiezhou         return Ok(metadata);
964abe3a6eaShanjiezhou     }
965abe3a6eaShanjiezhou }
966abe3a6eaShanjiezhou 
967abe3a6eaShanjiezhou /// Mapping from characters to glyph indices.
968abe3a6eaShanjiezhou pub trait GlyphMapping: Sync {
969abe3a6eaShanjiezhou     /// Maps a character to a glyph index.
970abe3a6eaShanjiezhou     ///
971abe3a6eaShanjiezhou     /// If `c` isn't included in the font the index of a suitable replacement glyph is returned.
972abe3a6eaShanjiezhou     fn index(&self, c: char) -> usize;
973abe3a6eaShanjiezhou }
974abe3a6eaShanjiezhou 
975abe3a6eaShanjiezhou impl<F> GlyphMapping for F
976abe3a6eaShanjiezhou where
977abe3a6eaShanjiezhou     F: Sync + Fn(char) -> usize,
978abe3a6eaShanjiezhou {
979abe3a6eaShanjiezhou     fn index(&self, c: char) -> usize {
980abe3a6eaShanjiezhou         self(c)
981abe3a6eaShanjiezhou     }
982abe3a6eaShanjiezhou }
983abe3a6eaShanjiezhou 
984abe3a6eaShanjiezhou /// 在默认窗口上输出一个字符
985abe3a6eaShanjiezhou /// ## 参数
986abe3a6eaShanjiezhou /// - character 字符
987abe3a6eaShanjiezhou /// - FRcolor 前景色(RGB)
988abe3a6eaShanjiezhou /// - BKcolor 背景色(RGB)
989abe3a6eaShanjiezhou 
990abe3a6eaShanjiezhou #[no_mangle]
991abe3a6eaShanjiezhou pub extern "C" fn rs_textui_putchar(character: u8, fr_color: u32, bk_color: u32) -> i32 {
99252da9a59SGnoCiYeH     let current_vcnum = CURRENT_VCNUM.load(Ordering::SeqCst);
99352da9a59SGnoCiYeH     if current_vcnum != -1 {
99452da9a59SGnoCiYeH         // tty已经初始化了之后才输出到屏幕
99552da9a59SGnoCiYeH         let fr = (fr_color & 0x00ff0000) >> 16;
99652da9a59SGnoCiYeH         let fg = (fr_color & 0x0000ff00) >> 8;
99752da9a59SGnoCiYeH         let fb = fr_color & 0x000000ff;
99852da9a59SGnoCiYeH         let br = (bk_color & 0x00ff0000) >> 16;
99952da9a59SGnoCiYeH         let bg = (bk_color & 0x0000ff00) >> 8;
100052da9a59SGnoCiYeH         let bb = bk_color & 0x000000ff;
100152da9a59SGnoCiYeH         let buf = format!(
100252da9a59SGnoCiYeH             "\x1B[38;2;{fr};{fg};{fb};48;2;{br};{bg};{bb}m{}\x1B[0m",
100352da9a59SGnoCiYeH             character as char
100452da9a59SGnoCiYeH         );
100552da9a59SGnoCiYeH         let port = TTY_PORTS[current_vcnum as usize].clone();
100652da9a59SGnoCiYeH         let tty = port.port_data().tty();
100752da9a59SGnoCiYeH         if tty.is_some() {
100852da9a59SGnoCiYeH             let tty = tty.unwrap();
100952da9a59SGnoCiYeH             return tty
101052da9a59SGnoCiYeH                 .write(tty.core(), buf.as_bytes(), buf.len())
101152da9a59SGnoCiYeH                 .map(|_| 0)
101252da9a59SGnoCiYeH                 .unwrap_or_else(|e| e.to_posix_errno());
101352da9a59SGnoCiYeH         }
101452da9a59SGnoCiYeH     }
1015abe3a6eaShanjiezhou     return textui_putchar(
1016abe3a6eaShanjiezhou         character as char,
1017abe3a6eaShanjiezhou         FontColor::from(fr_color),
1018abe3a6eaShanjiezhou         FontColor::from(bk_color),
1019abe3a6eaShanjiezhou     )
1020abe3a6eaShanjiezhou     .map(|_| 0)
1021abe3a6eaShanjiezhou     .unwrap_or_else(|e| e.to_posix_errno());
1022abe3a6eaShanjiezhou }
1023abe3a6eaShanjiezhou 
1024abe3a6eaShanjiezhou pub fn textui_putchar(
1025abe3a6eaShanjiezhou     character: char,
1026abe3a6eaShanjiezhou     fr_color: FontColor,
1027abe3a6eaShanjiezhou     bk_color: FontColor,
1028abe3a6eaShanjiezhou ) -> Result<(), SystemError> {
1029abe3a6eaShanjiezhou     if unsafe { TEXTUI_IS_INIT } {
1030abe3a6eaShanjiezhou         return textui_framework()
1031abe3a6eaShanjiezhou             .current_window
1032*e2841179SLoGin             .lock_irqsave()
1033abe3a6eaShanjiezhou             .textui_putchar_window(
1034abe3a6eaShanjiezhou                 character,
1035abe3a6eaShanjiezhou                 fr_color,
1036abe3a6eaShanjiezhou                 bk_color,
10371a72a751SLoGin                 textui_is_enable_put_to_window(),
1038abe3a6eaShanjiezhou             );
1039abe3a6eaShanjiezhou     } else {
1040abe3a6eaShanjiezhou         //未初始化暴力输出
1041abe3a6eaShanjiezhou         return no_init_textui_putchar_window(
1042abe3a6eaShanjiezhou             character,
1043abe3a6eaShanjiezhou             fr_color,
1044abe3a6eaShanjiezhou             bk_color,
10451a72a751SLoGin             textui_is_enable_put_to_window(),
1046abe3a6eaShanjiezhou         );
1047abe3a6eaShanjiezhou     }
1048abe3a6eaShanjiezhou }
1049abe3a6eaShanjiezhou 
1050fbe6becdSLoGin /// 向默认窗口输出一个字符串
1051fbe6becdSLoGin pub fn textui_putstr(
1052fbe6becdSLoGin     string: &str,
1053fbe6becdSLoGin     fr_color: FontColor,
1054fbe6becdSLoGin     bk_color: FontColor,
1055fbe6becdSLoGin ) -> Result<(), SystemError> {
1056fbe6becdSLoGin     let window = if unsafe { TEXTUI_IS_INIT } {
1057fbe6becdSLoGin         let fw = textui_framework();
1058fbe6becdSLoGin         let w = fw.current_window.clone();
1059fbe6becdSLoGin         Some(w)
1060fbe6becdSLoGin     } else {
1061fbe6becdSLoGin         None
1062fbe6becdSLoGin     };
1063fbe6becdSLoGin 
1064*e2841179SLoGin     let mut guard = window.as_ref().map(|w| w.lock_irqsave());
1065fbe6becdSLoGin 
1066fbe6becdSLoGin     for character in string.chars() {
1067fbe6becdSLoGin         if unsafe { TEXTUI_IS_INIT } {
1068fbe6becdSLoGin             guard.as_mut().unwrap().textui_putchar_window(
1069fbe6becdSLoGin                 character,
1070fbe6becdSLoGin                 fr_color,
1071fbe6becdSLoGin                 bk_color,
10721a72a751SLoGin                 textui_is_enable_put_to_window(),
1073fbe6becdSLoGin             )?;
1074fbe6becdSLoGin         } else {
1075fbe6becdSLoGin             no_init_textui_putchar_window(
1076fbe6becdSLoGin                 character,
1077fbe6becdSLoGin                 fr_color,
1078fbe6becdSLoGin                 bk_color,
10791a72a751SLoGin                 textui_is_enable_put_to_window(),
1080fbe6becdSLoGin             )?;
1081fbe6becdSLoGin         }
1082fbe6becdSLoGin     }
1083fbe6becdSLoGin 
1084fbe6becdSLoGin     return Ok(());
1085fbe6becdSLoGin }
1086fbe6becdSLoGin 
1087abe3a6eaShanjiezhou /// 初始化text ui框架
10885b59005fSLoGin #[inline(never)]
10895b59005fSLoGin pub fn textui_init() -> Result<i32, SystemError> {
10905b59005fSLoGin     textui_framwork_init();
1091abe3a6eaShanjiezhou 
1092abe3a6eaShanjiezhou     return Ok(0);
1093abe3a6eaShanjiezhou }
1094