xref: /DragonOS/kernel/src/libs/lib_ui/textui_no_alloc.rs (revision 7ae679ddd6481897a86523a52fad3b060254fa5b)
1 use core::{
2     intrinsics::unlikely,
3     sync::atomic::{AtomicI32, Ordering},
4 };
5 
6 use crate::{
7     driver::{
8         uart::uart_device::{c_uart_send, UartPort},
9         video::video_refresh_manager,
10     },
11     syscall::SystemError,
12 };
13 
14 use super::textui::{
15     FontColor, LineId, LineIndex, TextuiCharChromatic, TEXTUI_CHAR_HEIGHT, TEXTUI_CHAR_WIDTH,
16 };
17 
18 pub static TRUE_LINE_NUM: AtomicI32 = AtomicI32::new(0);
19 pub static CHAR_PER_LINE: AtomicI32 = AtomicI32::new(0);
20 /// textui 未初始化时直接向缓冲区写,不使用虚拟行
21 pub static NO_ALLOC_OPERATIONS_LINE: AtomicI32 = AtomicI32::new(0);
22 pub static NO_ALLOC_OPERATIONS_INDEX: AtomicI32 = AtomicI32::new(0);
23 
24 /// 当系统刚启动的时候,由于内存管理未初始化,而texiui需要动态内存分配。因此只能暂时暴力往屏幕(video_frame_buffer_info)输出信息
25 pub fn textui_init_no_alloc() {
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 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 
47     c_uart_send(UartPort::COM1.to_u16(), character as u8);
48 
49     // 进行换行操作
50     if unlikely(character == '\n') {
51         // 换行时还需要输出\r
52         c_uart_send(UartPort::COM1.to_u16(), 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