xref: /DragonOS/kernel/src/libs/lib_ui/textui_no_alloc.rs (revision 111c5407ccb7774695c8047cf895481d3387fda9)
1 use core::{
2     intrinsics::unlikely,
3     sync::atomic::{AtomicI32, Ordering},
4 };
5 
6 use crate::{
7     driver::{
8         tty::serial::serial8250::send_to_default_serial8250_port, video::video_refresh_manager,
9     },
10     syscall::SystemError,
11 };
12 
13 use super::textui::{
14     FontColor, LineId, LineIndex, TextuiCharChromatic, TEXTUI_CHAR_HEIGHT, TEXTUI_CHAR_WIDTH,
15 };
16 
17 pub static TRUE_LINE_NUM: AtomicI32 = AtomicI32::new(0);
18 pub static CHAR_PER_LINE: AtomicI32 = AtomicI32::new(0);
19 /// textui 未初始化时直接向缓冲区写,不使用虚拟行
20 pub static NO_ALLOC_OPERATIONS_LINE: AtomicI32 = AtomicI32::new(0);
21 pub static NO_ALLOC_OPERATIONS_INDEX: AtomicI32 = AtomicI32::new(0);
22 
23 /// 当系统刚启动的时候,由于内存管理未初始化,而texiui需要动态内存分配。因此只能暂时暴力往屏幕(video_frame_buffer_info)输出信息
24 pub fn textui_init_no_alloc(video_enabled: bool) {
25     if video_enabled {
26         let height = video_refresh_manager().device_buffer().height();
27         let width = video_refresh_manager().device_buffer().width();
28         TRUE_LINE_NUM.store((height / TEXTUI_CHAR_HEIGHT) as i32, Ordering::SeqCst);
29 
30         CHAR_PER_LINE.store((width / TEXTUI_CHAR_WIDTH) as i32, Ordering::SeqCst);
31     }
32 }
33 
34 pub fn no_init_textui_putchar_window(
35     character: char,
36     frcolor: FontColor,
37     bkcolor: FontColor,
38     is_put_to_window: bool,
39 ) -> Result<(), SystemError> {
40     if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) > TRUE_LINE_NUM.load(Ordering::SeqCst) {
41         NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
42     }
43     //字符'\0'代表ASCII码表中的空字符,表示字符串的结尾
44     if unlikely(character == '\0') {
45         return Ok(());
46     }
47     send_to_default_serial8250_port(&[character as u8]);
48 
49     // 进行换行操作
50     if unlikely(character == '\n') {
51         // 换行时还需要输出\r
52         send_to_default_serial8250_port(&[b'\r']);
53         if is_put_to_window == true {
54             NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
55             NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
56         }
57         return Ok(());
58     }
59     // 输出制表符
60     else if character == '\t' {
61         if is_put_to_window == true {
62             let char = TextuiCharChromatic::new(Some(' '), frcolor, bkcolor);
63 
64             //打印的空格数(注意将每行分成一个个表格,每个表格为8个字符)
65             let mut space_to_print = 8 - NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst) % 8;
66             while space_to_print > 0 {
67                 char.no_init_textui_render_chromatic(
68                     LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
69                     LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
70                 );
71                 NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
72                 space_to_print -= 1;
73             }
74             return Ok(());
75         }
76     }
77     // 字符 '\x08' 代表 ASCII 码中的退格字符。它在输出中的作用是将光标向左移动一个位置,并在该位置上输出后续的字符,从而实现字符的删除或替换。
78     else if character == '\x08' {
79         if is_put_to_window == true {
80             NO_ALLOC_OPERATIONS_INDEX.fetch_sub(1, Ordering::SeqCst);
81             let op_char = NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst);
82             if op_char >= 0 {
83                 let char = TextuiCharChromatic::new(Some(' '), frcolor, bkcolor);
84                 char.no_init_textui_render_chromatic(
85                     LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
86                     LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
87                 );
88 
89                 NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
90             }
91             // 需要向上缩一行
92             if op_char < 0 {
93                 // 上缩一行
94                 NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
95                 NO_ALLOC_OPERATIONS_LINE.fetch_sub(1, Ordering::SeqCst);
96 
97                 if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) < 0 {
98                     NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
99                 }
100             }
101         }
102     } else {
103         if is_put_to_window == true {
104             // 输出其他字符
105             let char = TextuiCharChromatic::new(Some(character), frcolor, bkcolor);
106 
107             if NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)
108                 == CHAR_PER_LINE.load(Ordering::SeqCst)
109             {
110                 NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
111                 NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
112             }
113             char.no_init_textui_render_chromatic(
114                 LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
115                 LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
116             );
117 
118             NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
119         }
120     }
121 
122     return Ok(());
123 }
124