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