xref: /DragonOS/kernel/src/libs/lib_ui/textui_no_alloc.rs (revision 4537ffb7e9afb2d96f2adcee32c8ac84b056d2e5)
1 use core::{
2     intrinsics::unlikely,
3     sync::atomic::{AtomicI32, Ordering},
4 };
5 
6 use crate::{
7     driver::uart::uart::{c_uart_send, UartPort},
8     include::bindings::bindings::video_frame_buffer_info,
9     syscall::SystemError,
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() {
24     TRUE_LINE_NUM.store(
25         unsafe { (video_frame_buffer_info.height / TEXTUI_CHAR_HEIGHT) as i32 },
26         Ordering::SeqCst,
27     );
28 
29     CHAR_PER_LINE.store(
30         unsafe { (video_frame_buffer_info.width / TEXTUI_CHAR_WIDTH) as i32 },
31         Ordering::SeqCst,
32     );
33 }
34 
35 pub fn no_init_textui_putchar_window(
36     character: char,
37     frcolor: FontColor,
38     bkcolor: FontColor,
39     is_put_to_window: bool,
40 ) -> Result<(), SystemError> {
41     if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) > TRUE_LINE_NUM.load(Ordering::SeqCst) {
42         NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
43     }
44     //字符'\0'代表ASCII码表中的空字符,表示字符串的结尾
45     if unlikely(character == '\0') {
46         return Ok(());
47     }
48 
49     c_uart_send(UartPort::COM1.to_u16(), character as u8);
50 
51     // 进行换行操作
52     if unlikely(character == '\n') {
53         // 换行时还需要输出\r
54         c_uart_send(UartPort::COM1.to_u16(), b'\r');
55         if is_put_to_window == true {
56             NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
57             NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
58         }
59         return Ok(());
60     }
61     // 输出制表符
62     else if character == '\t' {
63         if is_put_to_window == true {
64             let char = TextuiCharChromatic::new(Some(' '), frcolor, bkcolor);
65 
66             //打印的空格数(注意将每行分成一个个表格,每个表格为8个字符)
67             let mut space_to_print = 8 - NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst) % 8;
68             while space_to_print > 0 {
69                 char.no_init_textui_render_chromatic(
70                     LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
71                     LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
72                 );
73                 NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
74                 space_to_print -= 1;
75             }
76             return Ok(());
77         }
78     }
79     // 字符 '\x08' 代表 ASCII 码中的退格字符。它在输出中的作用是将光标向左移动一个位置,并在该位置上输出后续的字符,从而实现字符的删除或替换。
80     else if character == '\x08' {
81         if is_put_to_window == true {
82             NO_ALLOC_OPERATIONS_INDEX.fetch_sub(1, Ordering::SeqCst);
83             let op_char = NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst);
84             if op_char >= 0 {
85                 let char = TextuiCharChromatic::new(Some(' '), frcolor, bkcolor);
86                 char.no_init_textui_render_chromatic(
87                     LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
88                     LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
89                 );
90 
91                 NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
92             }
93             // 需要向上缩一行
94             if op_char < 0 {
95                 // 上缩一行
96                 NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
97                 NO_ALLOC_OPERATIONS_LINE.fetch_sub(1, Ordering::SeqCst);
98 
99                 if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) < 0 {
100                     NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
101                 }
102             }
103         }
104     } else {
105         if is_put_to_window == true {
106             // 输出其他字符
107             let char = TextuiCharChromatic::new(Some(character), frcolor, bkcolor);
108 
109             if NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)
110                 == CHAR_PER_LINE.load(Ordering::SeqCst)
111             {
112                 NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
113                 NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
114             }
115             char.no_init_textui_render_chromatic(
116                 LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
117                 LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
118             );
119 
120             NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
121         }
122     }
123 
124     return Ok(());
125 }
126