xref: /DragonOS/kernel/src/libs/lib_ui/textui_no_alloc.rs (revision 4b0170bd6bb374d0e9699a0076cc23b976ad6db7)
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 pub fn no_init_textui_putchar_window(
34     character: char,
35     frcolor: FontColor,
36     bkcolor: FontColor,
37     is_put_to_window: bool,
38 ) -> Result<(), SystemError> {
39     if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) >= TRUE_LINE_NUM.load(Ordering::SeqCst) {
40         NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
41     }
42     //字符'\0'代表ASCII码表中的空字符,表示字符串的结尾
43     if unlikely(character == '\0') {
44         return Ok(());
45     }
46     send_to_default_serial8250_port(&[character as u8]);
47 
48     // 进行换行操作
49     if unlikely(character == '\n') {
50         // 换行时还需要输出\r
51         send_to_default_serial8250_port(&[b'\r']);
52         if is_put_to_window {
53             NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
54             NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
55         }
56         return Ok(());
57     }
58     // 输出制表符
59     else if character == '\t' {
60         if is_put_to_window {
61             let char = TextuiCharChromatic::new(Some(' '), frcolor, bkcolor);
62 
63             //打印的空格数(注意将每行分成一个个表格,每个表格为8个字符)
64             let mut space_to_print = 8 - NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst) % 8;
65             while space_to_print > 0 {
66                 char.no_init_textui_render_chromatic(
67                     LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
68                     LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
69                 );
70                 NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
71                 space_to_print -= 1;
72             }
73             return Ok(());
74         }
75     }
76     // 字符 '\x08' 代表 ASCII 码中的退格字符。它在输出中的作用是将光标向左移动一个位置,并在该位置上输出后续的字符,从而实现字符的删除或替换。
77     else if character == '\x08' {
78         if is_put_to_window {
79             NO_ALLOC_OPERATIONS_INDEX.fetch_sub(1, Ordering::SeqCst);
80             let op_char = NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst);
81             if op_char >= 0 {
82                 let char = TextuiCharChromatic::new(Some(' '), frcolor, bkcolor);
83                 char.no_init_textui_render_chromatic(
84                     LineId::new(NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst)),
85                     LineIndex::new(NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst)),
86                 );
87 
88                 NO_ALLOC_OPERATIONS_INDEX.fetch_add(1, Ordering::SeqCst);
89             }
90             // 需要向上缩一行
91             if op_char < 0 {
92                 // 上缩一行
93                 NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
94                 NO_ALLOC_OPERATIONS_LINE.fetch_sub(1, Ordering::SeqCst);
95 
96                 if NO_ALLOC_OPERATIONS_LINE.load(Ordering::SeqCst) < 0 {
97                     NO_ALLOC_OPERATIONS_LINE.store(0, Ordering::SeqCst);
98                 }
99             }
100         }
101     } else if is_put_to_window {
102         // 输出其他字符
103         let char = TextuiCharChromatic::new(Some(character), frcolor, bkcolor);
104 
105         if NO_ALLOC_OPERATIONS_INDEX.load(Ordering::SeqCst) == CHAR_PER_LINE.load(Ordering::SeqCst)
106         {
107             NO_ALLOC_OPERATIONS_INDEX.store(0, Ordering::SeqCst);
108             NO_ALLOC_OPERATIONS_LINE.fetch_add(1, Ordering::SeqCst);
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     return Ok(());
119 }
120