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