|
@@ -4,31 +4,93 @@
|
|
|
#include "driver/uart/uart.h"
|
|
|
#include <common/string.h>
|
|
|
#include <common/printk.h>
|
|
|
+#include <common/atomic.h>
|
|
|
|
|
|
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;
|
|
|
}
|