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