mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-10 20:36:48 +00:00
new: 初步完成了textui的基本显示功能
This commit is contained in:
parent
36d55511ba
commit
17d5fea2cf
5
.vscode/settings.json
vendored
5
.vscode/settings.json
vendored
@ -117,7 +117,10 @@
|
|||||||
"sched.h": "c",
|
"sched.h": "c",
|
||||||
"preempt.h": "c",
|
"preempt.h": "c",
|
||||||
"softirq.h": "c",
|
"softirq.h": "c",
|
||||||
"screen_manager.h": "c"
|
"screen_manager.h": "c",
|
||||||
|
"textui.h": "c",
|
||||||
|
"atomic.h": "c",
|
||||||
|
"uart.h": "c"
|
||||||
},
|
},
|
||||||
"C_Cpp.errorSquiggles": "Enabled",
|
"C_Cpp.errorSquiggles": "Enabled",
|
||||||
"esbonio.sphinx.confDir": ""
|
"esbonio.sphinx.confDir": ""
|
||||||
|
@ -13,10 +13,11 @@
|
|||||||
#include <driver/video/video.h>
|
#include <driver/video/video.h>
|
||||||
#include "math.h"
|
#include "math.h"
|
||||||
#include <common/string.h>
|
#include <common/string.h>
|
||||||
|
#include <lib/libUI/textui.h>
|
||||||
|
|
||||||
struct printk_screen_info pos;
|
struct printk_screen_info pos;
|
||||||
|
|
||||||
static spinlock_t printk_lock;
|
static spinlock_t printk_lock={1};
|
||||||
static bool sw_show_scroll_animation = false; // 显示换行动画的开关
|
static bool sw_show_scroll_animation = false; // 显示换行动画的开关
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -662,49 +663,6 @@ static char *write_float_point_num(char *str, double num, int field_width, int p
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void putchar(uint *fb, int Xsize, int x, int y, unsigned int FRcolor, unsigned int BKcolor, unsigned char font)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* @brief 在屏幕上指定位置打印字符
|
|
||||||
*
|
|
||||||
* @param fb 帧缓存线性地址
|
|
||||||
* @param Xsize 行分辨率
|
|
||||||
* @param x 左上角列像素点位置
|
|
||||||
* @param y 左上角行像素点位置
|
|
||||||
* @param FRcolor 字体颜色
|
|
||||||
* @param BKcolor 背景颜色
|
|
||||||
* @param font 字符的bitmap
|
|
||||||
*/
|
|
||||||
|
|
||||||
//#if DEBUG
|
|
||||||
uart_send(COM1, font);
|
|
||||||
//#endif
|
|
||||||
|
|
||||||
unsigned char *font_ptr = font_ascii[font];
|
|
||||||
unsigned int *addr;
|
|
||||||
|
|
||||||
int testbit; // 用来测试某位是背景还是字体本身
|
|
||||||
|
|
||||||
for (int i = 0; i < pos.char_size_y; ++i)
|
|
||||||
{
|
|
||||||
// 计算出帧缓冲区的地址
|
|
||||||
addr = fb + Xsize * (y + i) + x;
|
|
||||||
testbit = (1 << (pos.char_size_x + 1));
|
|
||||||
for (int j = 0; j < pos.char_size_x; ++j)
|
|
||||||
{
|
|
||||||
//从左往右逐个测试相应位
|
|
||||||
testbit >>= 1;
|
|
||||||
if (*font_ptr & testbit)
|
|
||||||
*addr = FRcolor; // 字,显示前景色
|
|
||||||
else
|
|
||||||
*addr = BKcolor; // 背景色
|
|
||||||
|
|
||||||
++addr;
|
|
||||||
}
|
|
||||||
++font_ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 格式化打印字符串
|
* @brief 格式化打印字符串
|
||||||
*
|
*
|
||||||
@ -715,9 +673,6 @@ static void putchar(uint *fb, int Xsize, int x, int y, unsigned int FRcolor, uns
|
|||||||
int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ...)
|
int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint64_t rflags = 0; // 加锁后rflags存储到这里
|
|
||||||
spin_lock_irqsave(&printk_lock, rflags);
|
|
||||||
|
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
char buf[4096]; // vsprintf()的缓冲区
|
char buf[4096]; // vsprintf()的缓冲区
|
||||||
@ -733,47 +688,43 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, ..
|
|||||||
//输出换行
|
//输出换行
|
||||||
if (current == '\n')
|
if (current == '\n')
|
||||||
{
|
{
|
||||||
pos.x = 0;
|
|
||||||
++pos.y;
|
|
||||||
auto_newline();
|
|
||||||
}
|
|
||||||
else if (current == '\t') // 输出制表符
|
|
||||||
{
|
|
||||||
int space_to_print = 8 - pos.x % 8;
|
|
||||||
|
|
||||||
while (space_to_print--)
|
textui_putchar(current);
|
||||||
{
|
}
|
||||||
putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, ' ');
|
// else if (current == '\t') // 输出制表符
|
||||||
++pos.x;
|
// {
|
||||||
|
// int space_to_print = 8 - pos.x % 8;
|
||||||
|
|
||||||
auto_newline();
|
// while (space_to_print--)
|
||||||
}
|
// {
|
||||||
}
|
// textui_putchar(' ');
|
||||||
else if (current == '\b') // 退格
|
// ++pos.x;
|
||||||
{
|
// }
|
||||||
--pos.x;
|
// }
|
||||||
if (pos.x < 0)
|
// else if (current == '\b') // 退格
|
||||||
{
|
// {
|
||||||
--pos.y;
|
// --pos.x;
|
||||||
if (pos.y <= 0)
|
// if (pos.x < 0)
|
||||||
pos.x = pos.y = 0;
|
// {
|
||||||
else
|
// --pos.y;
|
||||||
pos.x = pos.max_x;
|
// if (pos.y <= 0)
|
||||||
}
|
// pos.x = pos.y = 0;
|
||||||
|
// else
|
||||||
|
// pos.x = pos.max_x;
|
||||||
|
// }
|
||||||
|
|
||||||
putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, ' ');
|
// textui_putchar(' ');
|
||||||
|
|
||||||
auto_newline();
|
// auto_newline();
|
||||||
}
|
// }
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, current);
|
if (current != '\0')
|
||||||
++pos.x;
|
textui_putchar(current);
|
||||||
auto_newline();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spin_unlock_irqrestore(&printk_lock, rflags);
|
// spin_unlock_irqrestore(&printk_lock, rflags);
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
all: screen_manager.o textui.o
|
all: screen_manager.o textui.o textui-render.o
|
||||||
|
|
||||||
CFLAGS += -I .
|
CFLAGS += -I .
|
||||||
|
|
||||||
@ -8,3 +8,6 @@ screen_manager.o: screen_manager.c
|
|||||||
|
|
||||||
textui.o: textui.c
|
textui.o: textui.c
|
||||||
gcc $(CFLAGS) -c textui.c -o textui.o
|
gcc $(CFLAGS) -c textui.c -o textui.o
|
||||||
|
|
||||||
|
textui-render.o: textui-render.c
|
||||||
|
gcc $(CFLAGS) -c textui-render.c -o textui-render.o
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
#include <driver/uart/uart.h>
|
#include <driver/uart/uart.h>
|
||||||
#include <driver/video/video.h>
|
#include <driver/video/video.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
extern struct scm_buffer_info_t video_frame_buffer_info;
|
extern struct scm_buffer_info_t video_frame_buffer_info;
|
||||||
static struct List scm_framework_list;
|
static struct List scm_framework_list;
|
||||||
static spinlock_t scm_register_lock; // 框架注册锁
|
static spinlock_t scm_register_lock; // 框架注册锁
|
||||||
@ -106,7 +104,7 @@ static int __check_ui_param(const char *name, const uint8_t type, const struct s
|
|||||||
{
|
{
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (!(type == SCM_FRAMWORK_TYPE_GUI || type == SCM_FRAMWORK_TYPE_TEXT))
|
if ((type == SCM_FRAMWORK_TYPE_GUI || type == SCM_FRAMWORK_TYPE_TEXT) == 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
if (ops == NULL)
|
if (ops == NULL)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -9,8 +9,8 @@
|
|||||||
#define SCM_BF_PIXEL (1 << 3) // 使用图像模式
|
#define SCM_BF_PIXEL (1 << 3) // 使用图像模式
|
||||||
|
|
||||||
// ui框架类型
|
// ui框架类型
|
||||||
#define SCM_FRAMWORK_TYPE_TEXT 0
|
#define SCM_FRAMWORK_TYPE_TEXT (uint8_t)0
|
||||||
#define SCM_FRAMWORK_TYPE_GUI 1
|
#define SCM_FRAMWORK_TYPE_GUI (uint8_t)1
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 帧缓冲区信息结构体
|
* @brief 帧缓冲区信息结构体
|
||||||
@ -47,7 +47,7 @@ struct scm_ui_framework_t
|
|||||||
uint8_t type;
|
uint8_t type;
|
||||||
struct scm_ui_framework_operations_t *ui_ops;
|
struct scm_ui_framework_operations_t *ui_ops;
|
||||||
struct scm_buffer_info_t *buf;
|
struct scm_buffer_info_t *buf;
|
||||||
} __attribute__((aligned(sizeof(uint64_t))));
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化屏幕管理模块
|
* @brief 初始化屏幕管理模块
|
||||||
|
155
kernel/lib/libUI/textui-render.c
Normal file
155
kernel/lib/libUI/textui-render.c
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
#include "textui.h"
|
||||||
|
#include <driver/uart/uart.h>
|
||||||
|
|
||||||
|
#define WHITE 0x00ffffff //白
|
||||||
|
#define BLACK 0x00000000 //黑
|
||||||
|
#define RED 0x00ff0000 //红
|
||||||
|
#define ORANGE 0x00ff8000 //橙
|
||||||
|
#define YELLOW 0x00ffff00 //黄
|
||||||
|
#define GREEN 0x0000ff00 //绿
|
||||||
|
#define BLUE 0x000000ff //蓝
|
||||||
|
#define INDIGO 0x0000ffff //靛
|
||||||
|
#define PURPLE 0x008000ff //紫
|
||||||
|
|
||||||
|
// 根据rgb计算出最终的颜色值
|
||||||
|
#define calculate_color(r, g, b) ((((r & 0xff) << 16) | ((g & 0xff) << 8) | (b & 0xff)) & 0x00ffffff)
|
||||||
|
|
||||||
|
extern struct scm_ui_framework_t textui_framework;
|
||||||
|
|
||||||
|
static void __textui_render_chromatic(uint16_t actual_line, uint16_t index, struct textui_char_chromatic_t *character);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 重新渲染整个虚拟行
|
||||||
|
*
|
||||||
|
* @param window 窗口结构体
|
||||||
|
* @param vline_id 虚拟行号
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int textui_refresh_vline(struct textui_window_t *window, uint16_t vline_id)
|
||||||
|
{
|
||||||
|
if (textui_is_chromatic(window->flags))
|
||||||
|
return textui_refresh_characters(window, vline_id, 0, window->chars_per_line);
|
||||||
|
else
|
||||||
|
return textui_refresh_characters(window, vline_id, 0, window->chars_per_line);
|
||||||
|
}
|
||||||
|
|
||||||
|
int textui_refresh_vlines(struct textui_window_t *window, uint16_t start, uint16_t count)
|
||||||
|
{
|
||||||
|
char bufff[16] = {0};
|
||||||
|
// uart_send_str(COM1, " BEGIN ");
|
||||||
|
for (int i = start; i < window->vlines_num && count > 0; ++i, --count)
|
||||||
|
{
|
||||||
|
// sprintk(bufff, "[ 1fresh: %d ] ", i);
|
||||||
|
// uart_send_str(COM1, bufff);
|
||||||
|
textui_refresh_vline(window, i);
|
||||||
|
}
|
||||||
|
start = 0;
|
||||||
|
while (count>0)
|
||||||
|
{
|
||||||
|
// sprintk(bufff, "[ 2fresh: %d ] ", start);
|
||||||
|
// uart_send_str(COM1, bufff);
|
||||||
|
// sprintk(bufff, " index=%d ", (window->vlines.chromatic)[start].index);
|
||||||
|
// uart_send_str(COM1, bufff);
|
||||||
|
textui_refresh_vline(window, start);
|
||||||
|
++start;
|
||||||
|
--count;
|
||||||
|
}
|
||||||
|
// uart_send_str(COM1, " END ");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 刷新某个虚拟行的连续n个字符对象
|
||||||
|
*
|
||||||
|
* @param window 窗口结构体
|
||||||
|
* @param vline_id 虚拟行号
|
||||||
|
* @param start 起始字符号
|
||||||
|
* @param count 要刷新的字符数量
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int textui_refresh_characters(struct textui_window_t *window, uint16_t vline_id, uint16_t start, uint16_t count)
|
||||||
|
{
|
||||||
|
if (window->id != __textui_get_current_window_id())
|
||||||
|
return 0;
|
||||||
|
// 判断虚拟行参数是否合法
|
||||||
|
if (unlikely(vline_id >= window->vlines_num && (start + count) > window->chars_per_line))
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
// 计算虚拟行对应的真实行
|
||||||
|
int actual_line_id = (int)vline_id - window->top_vline;
|
||||||
|
if (actual_line_id < 0)
|
||||||
|
actual_line_id += __textui_get_actual_lines();
|
||||||
|
// 判断真实行id是否合理
|
||||||
|
if (unlikely(actual_line_id < 0 || actual_line_id >= __textui_get_actual_lines()))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// 若是彩色像素模式
|
||||||
|
if (textui_is_chromatic(window->flags))
|
||||||
|
{
|
||||||
|
struct textui_vline_chromatic_t *vline = &(window->vlines.chromatic)[vline_id];
|
||||||
|
for (int i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
|
||||||
|
__textui_render_chromatic(actual_line_id, start + i, &vline->chars[start + i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 渲染彩色字符
|
||||||
|
*
|
||||||
|
* @param actual_line 真实行的行号
|
||||||
|
* @param index 列号
|
||||||
|
* @param character 要渲染的字符
|
||||||
|
*/
|
||||||
|
static void __textui_render_chromatic(uint16_t actual_line, uint16_t index, struct textui_char_chromatic_t *character)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief 在屏幕上指定位置打印字符
|
||||||
|
*
|
||||||
|
* @param x 左上角列像素点位置
|
||||||
|
* @param y 左上角行像素点位置
|
||||||
|
* @param FRcolor 字体颜色
|
||||||
|
* @param BKcolor 背景颜色
|
||||||
|
* @param font 字符的bitmap
|
||||||
|
*/
|
||||||
|
|
||||||
|
// #if DEBUG
|
||||||
|
// uart_send(COM1, font);
|
||||||
|
// #endif
|
||||||
|
|
||||||
|
unsigned char *font_ptr = font_ascii[(uint8_t)character->c];
|
||||||
|
unsigned int *addr;
|
||||||
|
uint32_t *fb = (uint32_t *)textui_framework.buf->vaddr;
|
||||||
|
// uint32_t FRcolor = YELLOW;
|
||||||
|
uint32_t FRcolor = calculate_color(character->Fr, character->Fg, character->Fb);
|
||||||
|
// uint32_t BKcolor = BLACK;
|
||||||
|
uint32_t BKcolor = calculate_color(character->Br, character->Bg, character->Bb);
|
||||||
|
|
||||||
|
uint32_t x = index * TEXTUI_CHAR_WIDTH;
|
||||||
|
uint32_t y = actual_line * TEXTUI_CHAR_HEIGHT;
|
||||||
|
|
||||||
|
int testbit; // 用来测试某位是背景还是字体本身
|
||||||
|
|
||||||
|
for (int i = 0; i < TEXTUI_CHAR_HEIGHT; ++i)
|
||||||
|
{
|
||||||
|
// 计算出帧缓冲区的地址
|
||||||
|
addr = (uint32_t *)(fb + textui_framework.buf->width * (y + i) + x);
|
||||||
|
|
||||||
|
testbit = (1 << (TEXTUI_CHAR_WIDTH + 1));
|
||||||
|
for (int j = 0; j < TEXTUI_CHAR_WIDTH; ++j)
|
||||||
|
{
|
||||||
|
// 从左往右逐个测试相应位
|
||||||
|
testbit >>= 1;
|
||||||
|
if (*font_ptr & testbit)
|
||||||
|
*addr = FRcolor; // 字,显示前景色
|
||||||
|
else
|
||||||
|
*addr = BKcolor; // 背景色
|
||||||
|
|
||||||
|
++addr;
|
||||||
|
}
|
||||||
|
++font_ptr;
|
||||||
|
}
|
||||||
|
}
|
@ -4,24 +4,86 @@
|
|||||||
#include "driver/uart/uart.h"
|
#include "driver/uart/uart.h"
|
||||||
#include <common/string.h>
|
#include <common/string.h>
|
||||||
#include <common/printk.h>
|
#include <common/printk.h>
|
||||||
|
#include <common/atomic.h>
|
||||||
|
|
||||||
struct scm_ui_framework_t textui_framework;
|
struct scm_ui_framework_t textui_framework;
|
||||||
|
static spinlock_t __window_id_lock = {1};
|
||||||
|
static uint32_t __window_max_id = 0;
|
||||||
|
|
||||||
|
// 暂时初始化16080个初始字符对象以及67个虚拟行对象
|
||||||
|
#define INITIAL_CHARS 16080
|
||||||
|
#define INITIAL_VLINES (int)(1080 / 16)
|
||||||
|
static struct textui_char_chromatic_t __initial_chars[INITIAL_CHARS] = {0};
|
||||||
|
static struct textui_vline_chromatic_t __initial_vlines[INITIAL_VLINES] = {0};
|
||||||
|
static struct textui_window_t __initial_window = {0}; // 初始窗口
|
||||||
|
static struct textui_private_info_t __private_info = {0};
|
||||||
|
static struct List __windows_list;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化window对象
|
||||||
|
*
|
||||||
|
* @param window 窗口对象
|
||||||
|
* @param flags 标志位
|
||||||
|
* @param vlines_num 虚拟行的总数
|
||||||
|
* @param vlines_ptr 虚拟行数组指针
|
||||||
|
* @param cperline 每行最大的字符数
|
||||||
|
*/
|
||||||
|
static int __textui_init_window(struct textui_window_t *window, uint8_t flags, uint16_t vlines_num, void *vlines_ptr, uint16_t cperline)
|
||||||
|
{
|
||||||
|
memset((window), 0, sizeof(struct textui_window_t));
|
||||||
|
list_init(&(window)->list);
|
||||||
|
window->lock.lock = 1;
|
||||||
|
spin_lock(&__window_id_lock);
|
||||||
|
window->id = __window_max_id++;
|
||||||
|
spin_unlock(&__window_id_lock);
|
||||||
|
window->flags = flags;
|
||||||
|
window->vlines_num = vlines_num;
|
||||||
|
window->vlines_used = 1;
|
||||||
|
window->top_vline = 0;
|
||||||
|
window->vline_operating = 0;
|
||||||
|
window->chars_per_line = cperline;
|
||||||
|
if (textui_is_chromatic(flags))
|
||||||
|
window->vlines.chromatic = vlines_ptr;
|
||||||
|
else
|
||||||
|
window->vlines.normal = vlines_ptr;
|
||||||
|
list_add(&__windows_list, &(window)->list);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化虚拟行对象
|
||||||
|
*
|
||||||
|
* @param vline 虚拟行对象指针
|
||||||
|
* @param chars_ptr 字符对象数组指针
|
||||||
|
*/
|
||||||
|
#define __textui_init_vline(vline, chars_ptr) \
|
||||||
|
do \
|
||||||
|
{ \
|
||||||
|
memset(vline, 0, sizeof(struct textui_vline_chromatic_t)); \
|
||||||
|
(vline)->index = 0; \
|
||||||
|
(vline)->chars = chars_ptr; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
int textui_install_handler(struct scm_buffer_info_t *buf)
|
int textui_install_handler(struct scm_buffer_info_t *buf)
|
||||||
{
|
{
|
||||||
return printk_init(buf);
|
// return printk_init(buf);
|
||||||
|
uart_send_str(COM1, "textui_install_handler");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int textui_uninstall_handler(void *args)
|
int textui_uninstall_handler(void *args)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int textui_enable_handler(void *args)
|
int textui_enable_handler(void *args)
|
||||||
{
|
{
|
||||||
|
uart_send_str(COM1, "textui_enable_handler");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int textui_disable_handler(void *args)
|
int textui_disable_handler(void *args)
|
||||||
{
|
{
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int textui_change_handler(struct scm_buffer_info_t *buf)
|
int textui_change_handler(struct scm_buffer_info_t *buf)
|
||||||
@ -41,6 +103,172 @@ struct scm_ui_framework_operations_t textui_ops =
|
|||||||
.disable = &textui_disable_handler,
|
.disable = &textui_disable_handler,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取textui的帧缓冲区能容纳的内容的行数
|
||||||
|
*
|
||||||
|
* @return uint16_t
|
||||||
|
*/
|
||||||
|
uint16_t __textui_get_actual_lines()
|
||||||
|
{
|
||||||
|
return __private_info.actual_line;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取当前渲染的窗口的id
|
||||||
|
*
|
||||||
|
* @return uint16_t
|
||||||
|
*/
|
||||||
|
uint32_t __textui_get_current_window_id()
|
||||||
|
{
|
||||||
|
return __private_info.current_window->id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 插入换行
|
||||||
|
*
|
||||||
|
* @param window 窗口结构体
|
||||||
|
* @param vline_id 虚拟行号
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
static int __textui_new_line(struct textui_window_t *window, uint16_t vline_id)
|
||||||
|
{
|
||||||
|
// todo: 支持在两个虚拟行之间插入一个新行
|
||||||
|
|
||||||
|
++window->vline_operating;
|
||||||
|
|
||||||
|
if (unlikely(window->vline_operating == window->vlines_num))
|
||||||
|
window->vline_operating = 0;
|
||||||
|
struct textui_vline_chromatic_t *vline = &window->vlines.chromatic[window->vline_operating];
|
||||||
|
memset(vline->chars, 0, sizeof(struct textui_char_chromatic_t) * window->chars_per_line);
|
||||||
|
vline->index = 0;
|
||||||
|
|
||||||
|
if (likely(window->vlines_used == window->vlines_num)) // 需要滚动屏幕
|
||||||
|
{
|
||||||
|
// uart_send_str(COM1, " scroll, top vline= ");
|
||||||
|
++window->top_vline;
|
||||||
|
// uart_send(COM1, '0' + window->top_vline);
|
||||||
|
if (unlikely(window->top_vline >= window->vlines_num))
|
||||||
|
window->top_vline = 0;
|
||||||
|
|
||||||
|
// int delta = ABS((int)window->vline_operating - (int)window->top_vline);
|
||||||
|
// 刷新所有行
|
||||||
|
textui_refresh_vlines(window, window->top_vline, window->vlines_num);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
++window->vlines_used;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static int __textui_putchar_window(struct textui_window_t *window, uint16_t character)
|
||||||
|
{
|
||||||
|
if (textui_is_chromatic(window->flags)) // 启用彩色字符
|
||||||
|
{
|
||||||
|
struct textui_vline_chromatic_t *vline = &window->vlines.chromatic[window->vline_operating];
|
||||||
|
|
||||||
|
vline->chars[vline->index].c = character;
|
||||||
|
vline->chars[vline->index].Fr = 0xff;
|
||||||
|
vline->chars[vline->index].Fg = 0xff;
|
||||||
|
vline->chars[vline->index].Fb = 0xff;
|
||||||
|
vline->chars[vline->index].Br = 0;
|
||||||
|
vline->chars[vline->index].Bg = 0;
|
||||||
|
vline->chars[vline->index].Bb = 0;
|
||||||
|
++vline->index;
|
||||||
|
textui_refresh_characters(window, window->vline_operating, vline->index - 1, 1);
|
||||||
|
// 换行
|
||||||
|
if (vline->index >= window->chars_per_line)
|
||||||
|
{
|
||||||
|
__textui_new_line(window, window->vline_operating);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// todo: 支持纯文本字符
|
||||||
|
while (1)
|
||||||
|
pause();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* @brief 在指定窗口上输出一个字符
|
||||||
|
*
|
||||||
|
* @param window 窗口
|
||||||
|
* @param character 字符
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int textui_putchar_window(struct textui_window_t *window, uint16_t character)
|
||||||
|
{
|
||||||
|
if (unlikely(character == '\0'))
|
||||||
|
return 0;
|
||||||
|
if (!textui_is_chromatic(window->flags)) // 暂不支持纯文本窗口
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
uint64_t rflags = 0; // 加锁后rflags存储到这里
|
||||||
|
spin_lock_irqsave(&window->lock, rflags);
|
||||||
|
uart_send(COM1, character);
|
||||||
|
if (unlikely(character == '\n'))
|
||||||
|
{
|
||||||
|
__textui_new_line(window, window->vline_operating);
|
||||||
|
spin_unlock_irqrestore(&window->lock, rflags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (character == '\t') // 输出制表符
|
||||||
|
{
|
||||||
|
int space_to_print = 8 - window->vlines.chromatic[window->vline_operating].index % 8;
|
||||||
|
|
||||||
|
while (space_to_print--)
|
||||||
|
{
|
||||||
|
__textui_putchar_window(window, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (character == '\b') // 退格
|
||||||
|
{
|
||||||
|
|
||||||
|
--window->vlines.chromatic[window->vline_operating].index;
|
||||||
|
{
|
||||||
|
uint16_t tmp = window->vlines.chromatic[window->vline_operating].index;
|
||||||
|
window->vlines.chromatic[window->vline_operating].chars[tmp].c = ' ';
|
||||||
|
textui_refresh_characters(window, window->vline_operating, tmp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 需要向上缩一行
|
||||||
|
if (window->vlines.chromatic[window->vline_operating].index < 0)
|
||||||
|
{
|
||||||
|
window->vlines.chromatic[window->vline_operating].index = 0;
|
||||||
|
memset(window->vlines.chromatic[window->vline_operating].chars, 0, sizeof(struct textui_char_chromatic_t) * window->chars_per_line);
|
||||||
|
--window->vline_operating;
|
||||||
|
if (unlikely(window->vline_operating < 0))
|
||||||
|
window->vline_operating = window->vlines_num - 1;
|
||||||
|
|
||||||
|
// 考虑是否向上滚动
|
||||||
|
if (likely(window->vlines_used >= __private_info.actual_line))
|
||||||
|
{
|
||||||
|
--window->top_vline;
|
||||||
|
if (unlikely(window->top_vline < 0))
|
||||||
|
window->top_vline = window->vlines_num - 1;
|
||||||
|
}
|
||||||
|
--window->vlines_used;
|
||||||
|
textui_refresh_vlines(window, window->top_vline, __private_info.actual_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
__textui_putchar_window(window, character);
|
||||||
|
|
||||||
|
spin_unlock_irqrestore(&window->lock, rflags);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 在默认窗口上输出一个字符
|
||||||
|
*
|
||||||
|
* @param character 字符
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int textui_putchar(uint16_t character)
|
||||||
|
{
|
||||||
|
|
||||||
|
return textui_putchar_window(__private_info.default_window, character);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化text ui框架
|
* @brief 初始化text ui框架
|
||||||
*
|
*
|
||||||
@ -48,14 +276,20 @@ struct scm_ui_framework_operations_t textui_ops =
|
|||||||
*/
|
*/
|
||||||
int textui_init()
|
int textui_init()
|
||||||
{
|
{
|
||||||
memset(&textui_framework, 0, sizeof(textui_framework));
|
spin_init(&__window_id_lock);
|
||||||
|
__window_max_id = 0;
|
||||||
|
list_init(&__windows_list);
|
||||||
|
memset(&textui_framework, 0, sizeof(struct scm_ui_framework_t));
|
||||||
|
memset(&__private_info, 0, sizeof(struct textui_private_info_t));
|
||||||
|
|
||||||
io_mfence();
|
io_mfence();
|
||||||
char name[] = "textUI";
|
char name[] = "textUI";
|
||||||
strcpy(textui_framework.name, name);
|
strcpy(textui_framework.name, name);
|
||||||
|
|
||||||
textui_framework.ui_ops = &textui_ops;
|
textui_framework.ui_ops = &textui_ops;
|
||||||
textui_framework.type = SCM_FRAMWORK_TYPE_TEXT;
|
textui_framework.type = 0;
|
||||||
uart_send_str(COM1, "12121");
|
|
||||||
|
// 注册框架到屏幕管理器
|
||||||
int retval = scm_register(&textui_framework);
|
int retval = scm_register(&textui_framework);
|
||||||
if (retval != 0)
|
if (retval != 0)
|
||||||
{
|
{
|
||||||
@ -63,6 +297,26 @@ int textui_init()
|
|||||||
while (1)
|
while (1)
|
||||||
pause();
|
pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint16_t chars_per_vline = textui_framework.buf->width / TEXTUI_CHAR_WIDTH;
|
||||||
|
uint16_t total_vlines = textui_framework.buf->height / TEXTUI_CHAR_HEIGHT;
|
||||||
|
int cnt = chars_per_vline * total_vlines;
|
||||||
|
|
||||||
|
struct textui_vline_chromatic_t *vl_ptr = __initial_vlines;
|
||||||
|
struct textui_char_chromatic_t *ch_ptr = __initial_chars;
|
||||||
|
|
||||||
|
// 初始化虚拟行
|
||||||
|
for (int i = 0; i < total_vlines; ++i)
|
||||||
|
{
|
||||||
|
__textui_init_vline((vl_ptr + i), (ch_ptr + i * chars_per_vline));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化窗口
|
||||||
|
__textui_init_window((&__initial_window), TEXTUI_WF_CHROMATIC, total_vlines, __initial_vlines, chars_per_vline);
|
||||||
|
__private_info.current_window = &__initial_window;
|
||||||
|
__private_info.default_window = &__initial_window;
|
||||||
|
__private_info.actual_line = textui_framework.buf->height / TEXTUI_CHAR_HEIGHT;
|
||||||
|
|
||||||
uart_send_str(COM1, "text ui initialized");
|
uart_send_str(COM1, "text ui initialized");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
@ -1,4 +1,152 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include <common/glib.h>
|
||||||
|
#include <common/sys/types.h>
|
||||||
|
#include <common/spinlock.h>
|
||||||
|
|
||||||
|
// 文本窗口标志位
|
||||||
|
// 文本窗口是否为彩色
|
||||||
|
#define TEXTUI_WF_CHROMATIC (1 << 0)
|
||||||
|
|
||||||
|
// 窗口是否启用彩色字符
|
||||||
|
#define textui_is_chromatic(flag) ((flag)&TEXTUI_WF_CHROMATIC)
|
||||||
|
|
||||||
|
// 每个字符的宽度和高度(像素)
|
||||||
|
#define TEXTUI_CHAR_WIDTH 8
|
||||||
|
#define TEXTUI_CHAR_HEIGHT 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 黑白字符对象
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct textui_char_normal_t
|
||||||
|
{
|
||||||
|
char c;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 彩色字符对象
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct textui_char_chromatic_t
|
||||||
|
{
|
||||||
|
uint16_t c; // 字符
|
||||||
|
// 前景色
|
||||||
|
uint8_t Fr; // 红
|
||||||
|
uint8_t Fg; // 绿
|
||||||
|
uint8_t Fb; // 蓝
|
||||||
|
|
||||||
|
// 背景色
|
||||||
|
uint8_t Br;
|
||||||
|
uint8_t Bg;
|
||||||
|
uint8_t Bb;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 注意!!! 请保持vline结构体的大小、成员变量命名相等!
|
||||||
|
/**
|
||||||
|
* @brief 单色显示的虚拟行结构体
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct textui_vline_normal_t
|
||||||
|
{
|
||||||
|
struct textui_char_normal_t *chars; // 字符对象数组
|
||||||
|
uint16_t index; // 当前操作的位置
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 彩色显示的虚拟行结构体
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct textui_vline_chromatic_t
|
||||||
|
{
|
||||||
|
struct textui_char_chromatic_t *chars;
|
||||||
|
uint16_t index; // 当前操作的位置
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief textu ui 框架的文本窗口结构体
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
struct textui_window_t
|
||||||
|
{
|
||||||
|
struct List list;
|
||||||
|
|
||||||
|
uint32_t id; // 窗口id
|
||||||
|
uint16_t vlines_num; // 虚拟行总数
|
||||||
|
uint16_t vlines_used; // 当前已经使用了的虚拟行总数
|
||||||
|
|
||||||
|
// 指向虚拟行的数组的指针(二选一)
|
||||||
|
union
|
||||||
|
{
|
||||||
|
struct textui_vline_normal_t *normal;
|
||||||
|
struct textui_vline_chromatic_t *chromatic;
|
||||||
|
} vlines;
|
||||||
|
|
||||||
|
uint16_t top_vline; // 位于最顶上的那一个虚拟行的行号
|
||||||
|
uint16_t vline_operating; // 正在操作的vline
|
||||||
|
uint16_t chars_per_line; // 每行最大容纳的字符数
|
||||||
|
uint8_t flags; // 窗口flag
|
||||||
|
spinlock_t lock; // 窗口操作锁
|
||||||
|
};
|
||||||
|
|
||||||
|
struct textui_private_info_t
|
||||||
|
{
|
||||||
|
uint16_t actual_line; // 真实行的数量
|
||||||
|
struct textui_window_t *current_window; // 当前的主窗口
|
||||||
|
struct textui_window_t *default_window; // 默认print到的窗口
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 重新渲染整个虚拟行
|
||||||
|
*
|
||||||
|
* @param window 窗口结构体
|
||||||
|
* @param vline_id 虚拟行号
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int textui_refresh_vline(struct textui_window_t *window, uint16_t vline_id);
|
||||||
|
|
||||||
|
int textui_refresh_vlines(struct textui_window_t *window, uint16_t start, uint16_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 刷新某个虚拟行的连续n个字符对象
|
||||||
|
*
|
||||||
|
* @param window 窗口结构体
|
||||||
|
* @param vline_id 虚拟行号
|
||||||
|
* @param start 起始字符号
|
||||||
|
* @param count 要刷新的字符数量
|
||||||
|
* @return int 错误码
|
||||||
|
*/
|
||||||
|
int textui_refresh_characters(struct textui_window_t *window, uint16_t vline_id, uint16_t start, uint16_t count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 在指定窗口上输出一个字符
|
||||||
|
*
|
||||||
|
* @param window 窗口
|
||||||
|
* @param character 字符
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int textui_putchar_window(struct textui_window_t *window, uint16_t character);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 在默认窗口上输出一个字符
|
||||||
|
*
|
||||||
|
* @param character 字符
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
int textui_putchar(uint16_t character);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取textui的帧缓冲区能容纳的内容的行数
|
||||||
|
*
|
||||||
|
* @return uint16_t
|
||||||
|
*/
|
||||||
|
uint16_t __textui_get_actual_lines();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 获取当前渲染的窗口的id
|
||||||
|
*
|
||||||
|
* @return uint16_t
|
||||||
|
*/
|
||||||
|
uint32_t __textui_get_current_window_id();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 初始化text ui框架
|
* @brief 初始化text ui框架
|
||||||
|
@ -76,11 +76,9 @@ void system_initialize()
|
|||||||
|
|
||||||
scm_init();
|
scm_init();
|
||||||
textui_init();
|
textui_init();
|
||||||
|
// kinfo("Kernel Starting...");
|
||||||
kinfo("Kernel Starting...");
|
|
||||||
|
|
||||||
// 重新加载gdt和idt
|
// 重新加载gdt和idt
|
||||||
|
|
||||||
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
ul tss_item_addr = (ul)phys_2_virt(0x7c00);
|
||||||
|
|
||||||
_stack_start = head_stack_start; // 保存init proc的栈基地址(由于之后取消了地址重映射,因此必须在这里重新保存)
|
_stack_start = head_stack_start; // 保存init proc的栈基地址(由于之后取消了地址重映射,因此必须在这里重新保存)
|
||||||
@ -100,6 +98,7 @@ void system_initialize()
|
|||||||
|
|
||||||
// 初始化内存管理单元
|
// 初始化内存管理单元
|
||||||
mm_init();
|
mm_init();
|
||||||
|
|
||||||
// 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
|
// 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。
|
||||||
// 原因是,系统启动初期,framebuffer被映射到48M地址处,
|
// 原因是,系统启动初期,framebuffer被映射到48M地址处,
|
||||||
// mm初始化完毕后,若不重新初始化显示驱动,将会导致错误的数据写入内存,从而造成其他模块崩溃
|
// mm初始化完毕后,若不重新初始化显示驱动,将会导致错误的数据写入内存,从而造成其他模块崩溃
|
||||||
@ -165,7 +164,6 @@ void system_initialize()
|
|||||||
process_init();
|
process_init();
|
||||||
// 启用double buffer
|
// 启用double buffer
|
||||||
scm_enable_double_buffer();
|
scm_enable_double_buffer();
|
||||||
|
|
||||||
io_mfence();
|
io_mfence();
|
||||||
|
|
||||||
// fat32_init();
|
// fat32_init();
|
||||||
@ -175,6 +173,7 @@ void system_initialize()
|
|||||||
// 系统初始化到此结束,剩下的初始化功能应当放在初始内核线程中执行
|
// 系统初始化到此结束,剩下的初始化功能应当放在初始内核线程中执行
|
||||||
apic_timer_init();
|
apic_timer_init();
|
||||||
io_mfence();
|
io_mfence();
|
||||||
|
while(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//操作系统内核从这里开始执行
|
//操作系统内核从这里开始执行
|
||||||
|
Loading…
x
Reference in New Issue
Block a user