From 17d5fea2cf92ca949ec08b539f76984078ef525a Mon Sep 17 00:00:00 2001 From: fslongjin Date: Thu, 4 Aug 2022 21:40:26 +0800 Subject: [PATCH] =?UTF-8?q?new:=20=E5=88=9D=E6=AD=A5=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E4=BA=86textui=E7=9A=84=E5=9F=BA=E6=9C=AC=E6=98=BE=E7=A4=BA?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vscode/settings.json | 5 +- kernel/common/printk.c | 111 ++++--------- kernel/lib/libUI/Makefile | 7 +- kernel/lib/libUI/screen_manager.c | 8 +- kernel/lib/libUI/screen_manager.h | 6 +- kernel/lib/libUI/textui-render.c | 155 +++++++++++++++++ kernel/lib/libUI/textui.c | 266 +++++++++++++++++++++++++++++- kernel/lib/libUI/textui.h | 152 ++++++++++++++++- kernel/main.c | 9 +- 9 files changed, 615 insertions(+), 104 deletions(-) create mode 100644 kernel/lib/libUI/textui-render.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 7aa52e35..413ca78d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -117,7 +117,10 @@ "sched.h": "c", "preempt.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", "esbonio.sphinx.confDir": "" diff --git a/kernel/common/printk.c b/kernel/common/printk.c index 6bc96350..db2bc758 100644 --- a/kernel/common/printk.c +++ b/kernel/common/printk.c @@ -13,10 +13,11 @@ #include #include "math.h" #include +#include struct printk_screen_info pos; -static spinlock_t printk_lock; +static spinlock_t printk_lock={1}; 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; } -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 格式化打印字符串 * @@ -714,10 +672,7 @@ 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, ...) { - - uint64_t rflags = 0; // 加锁后rflags存储到这里 - spin_lock_irqsave(&printk_lock, rflags); - + va_list args; va_start(args, fmt); char buf[4096]; // vsprintf()的缓冲区 @@ -733,47 +688,43 @@ int printk_color(unsigned int FRcolor, unsigned int BKcolor, const char *fmt, .. //输出换行 if (current == '\n') { - pos.x = 0; - ++pos.y; - auto_newline(); + + textui_putchar(current); } - else if (current == '\t') // 输出制表符 - { - int space_to_print = 8 - pos.x % 8; + // else if (current == '\t') // 输出制表符 + // { + // int space_to_print = 8 - pos.x % 8; - while (space_to_print--) - { - putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, ' '); - ++pos.x; + // while (space_to_print--) + // { + // textui_putchar(' '); + // ++pos.x; + // } + // } + // else if (current == '\b') // 退格 + // { + // --pos.x; + // if (pos.x < 0) + // { + // --pos.y; + // if (pos.y <= 0) + // pos.x = pos.y = 0; + // else + // pos.x = pos.max_x; + // } - auto_newline(); - } - } - else if (current == '\b') // 退格 - { - --pos.x; - if (pos.x < 0) - { - --pos.y; - if (pos.y <= 0) - pos.x = pos.y = 0; - else - pos.x = pos.max_x; - } + // textui_putchar(' '); - putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, ' '); - - auto_newline(); - } + // auto_newline(); + // } else { - putchar(pos.FB_address, pos.width, pos.x * pos.char_size_x, pos.y * pos.char_size_y, FRcolor, BKcolor, current); - ++pos.x; - auto_newline(); + if (current != '\0') + textui_putchar(current); } } - spin_unlock_irqrestore(&printk_lock, rflags); + // spin_unlock_irqrestore(&printk_lock, rflags); return i; } diff --git a/kernel/lib/libUI/Makefile b/kernel/lib/libUI/Makefile index bbf427d1..1ad8edec 100644 --- a/kernel/lib/libUI/Makefile +++ b/kernel/lib/libUI/Makefile @@ -1,5 +1,5 @@ -all: screen_manager.o textui.o +all: screen_manager.o textui.o textui-render.o CFLAGS += -I . @@ -7,4 +7,7 @@ screen_manager.o: screen_manager.c gcc $(CFLAGS) -c screen_manager.c -o screen_manager.o textui.o: textui.c - gcc $(CFLAGS) -c textui.c -o textui.o \ No newline at end of file + gcc $(CFLAGS) -c textui.c -o textui.o + +textui-render.o: textui-render.c + gcc $(CFLAGS) -c textui-render.c -o textui-render.o diff --git a/kernel/lib/libUI/screen_manager.c b/kernel/lib/libUI/screen_manager.c index ef00e19a..dd8dd670 100644 --- a/kernel/lib/libUI/screen_manager.c +++ b/kernel/lib/libUI/screen_manager.c @@ -8,8 +8,6 @@ #include #include - - extern struct scm_buffer_info_t video_frame_buffer_info; static struct List scm_framework_list; static spinlock_t scm_register_lock; // 框架注册锁 @@ -32,7 +30,7 @@ static struct scm_buffer_info_t *__create_buffer(uint64_t type) struct scm_buffer_info_t *buf = (struct scm_buffer_info_t *)kmalloc(sizeof(struct scm_buffer_info_t), 0); if (buf == NULL) - return (void*)-ENOMEM; + return (void *)-ENOMEM; memset(buf, 0, sizeof(struct scm_buffer_info_t)); buf->bit_depth = video_frame_buffer_info.bit_depth; buf->flags = SCM_BF_DB; @@ -52,7 +50,7 @@ static struct scm_buffer_info_t *__create_buffer(uint64_t type) return buf; failed:; kfree(buf); - return (void*)-ENOMEM; + return (void *)-ENOMEM; } /** @@ -106,7 +104,7 @@ static int __check_ui_param(const char *name, const uint8_t type, const struct s { if (name == NULL) 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; if (ops == NULL) return -EINVAL; diff --git a/kernel/lib/libUI/screen_manager.h b/kernel/lib/libUI/screen_manager.h index 7ed2781f..36c77513 100644 --- a/kernel/lib/libUI/screen_manager.h +++ b/kernel/lib/libUI/screen_manager.h @@ -9,8 +9,8 @@ #define SCM_BF_PIXEL (1 << 3) // 使用图像模式 // ui框架类型 -#define SCM_FRAMWORK_TYPE_TEXT 0 -#define SCM_FRAMWORK_TYPE_GUI 1 +#define SCM_FRAMWORK_TYPE_TEXT (uint8_t)0 +#define SCM_FRAMWORK_TYPE_GUI (uint8_t)1 /** * @brief 帧缓冲区信息结构体 @@ -47,7 +47,7 @@ struct scm_ui_framework_t uint8_t type; struct scm_ui_framework_operations_t *ui_ops; struct scm_buffer_info_t *buf; -} __attribute__((aligned(sizeof(uint64_t)))); +}; /** * @brief 初始化屏幕管理模块 diff --git a/kernel/lib/libUI/textui-render.c b/kernel/lib/libUI/textui-render.c new file mode 100644 index 00000000..0365758f --- /dev/null +++ b/kernel/lib/libUI/textui-render.c @@ -0,0 +1,155 @@ +#include "textui.h" +#include + +#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; + } +} \ No newline at end of file diff --git a/kernel/lib/libUI/textui.c b/kernel/lib/libUI/textui.c index 940fa23c..b572ef42 100644 --- a/kernel/lib/libUI/textui.c +++ b/kernel/lib/libUI/textui.c @@ -4,31 +4,93 @@ #include "driver/uart/uart.h" #include #include +#include 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) { - return printk_init(buf); + // return printk_init(buf); + uart_send_str(COM1, "textui_install_handler"); + return 0; } int textui_uninstall_handler(void *args) { + return 0; } int textui_enable_handler(void *args) { + uart_send_str(COM1, "textui_enable_handler"); + return 0; } int textui_disable_handler(void *args) { + return 0; } int textui_change_handler(struct scm_buffer_info_t *buf) { - memcpy((void*)buf->vaddr, (void*)(textui_framework.buf->vaddr), textui_framework.buf->size); + memcpy((void *)buf->vaddr, (void *)(textui_framework.buf->vaddr), textui_framework.buf->size); textui_framework.buf = buf; - set_pos_VBE_FB_addr((uint*)buf->vaddr); + set_pos_VBE_FB_addr((uint *)buf->vaddr); return 0; } @@ -41,6 +103,172 @@ struct scm_ui_framework_operations_t textui_ops = .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框架 * @@ -48,14 +276,20 @@ struct scm_ui_framework_operations_t textui_ops = */ 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(); char name[] = "textUI"; strcpy(textui_framework.name, name); textui_framework.ui_ops = &textui_ops; - textui_framework.type = SCM_FRAMWORK_TYPE_TEXT; - uart_send_str(COM1, "12121"); + textui_framework.type = 0; + + // 注册框架到屏幕管理器 int retval = scm_register(&textui_framework); if (retval != 0) { @@ -63,6 +297,26 @@ int textui_init() while (1) 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"); return 0; } \ No newline at end of file diff --git a/kernel/lib/libUI/textui.h b/kernel/lib/libUI/textui.h index 30b39011..646b061b 100644 --- a/kernel/lib/libUI/textui.h +++ b/kernel/lib/libUI/textui.h @@ -1,8 +1,156 @@ #pragma once +#include +#include +#include + +// 文本窗口标志位 +// 文本窗口是否为彩色 +#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框架 - * - * @return int + * + * @return int */ int textui_init(); \ No newline at end of file diff --git a/kernel/main.c b/kernel/main.c index fd0f4e39..33fc27c1 100644 --- a/kernel/main.c +++ b/kernel/main.c @@ -76,11 +76,9 @@ void system_initialize() scm_init(); textui_init(); + // kinfo("Kernel Starting..."); - kinfo("Kernel Starting..."); - // 重新加载gdt和idt - ul tss_item_addr = (ul)phys_2_virt(0x7c00); _stack_start = head_stack_start; // 保存init proc的栈基地址(由于之后取消了地址重映射,因此必须在这里重新保存) @@ -100,6 +98,7 @@ void system_initialize() // 初始化内存管理单元 mm_init(); + // 内存管理单元初始化完毕后,需要立即重新初始化显示驱动。 // 原因是,系统启动初期,framebuffer被映射到48M地址处, // mm初始化完毕后,若不重新初始化显示驱动,将会导致错误的数据写入内存,从而造成其他模块崩溃 @@ -161,11 +160,10 @@ void system_initialize() io_mfence(); // current_pcb->preempt_count = 0; // kdebug("cpu_get_core_crysral_freq()=%ld", cpu_get_core_crysral_freq()); - + process_init(); // 启用double buffer scm_enable_double_buffer(); - io_mfence(); // fat32_init(); @@ -175,6 +173,7 @@ void system_initialize() // 系统初始化到此结束,剩下的初始化功能应当放在初始内核线程中执行 apic_timer_init(); io_mfence(); + while(1); } //操作系统内核从这里开始执行