Chapter 178 · XUI 专业控件

Terminal 终端基础

嵌入式终端模拟器:单元格网格、ANSI 转义序列解析、滚动缓冲、颜色配置。

178

概念

Terminal 控件是完整的终端模拟器:
• 单元格网格:Columns × Rows 的字符矩阵
• ANSI 解析:支持 SGR/光标移动/清屏等转义序列
• Scrollback:历史行缓冲区,可配置上限
• 输入回调:用户键入数据通过回调传递给进程
• 颜色主题:16 色 + 前景/背景/光标/选区颜色

API 速查

函数说明
int xuiTerminalCreate(xui_context pCtx, xui_widget* ppW, const xui_terminal_desc_t* pDesc)创建终端
int xuiTerminalWrite(pW, pData, iSize)写入二进制数据
int xuiTerminalWriteText(pW, sText)写入文本
int xuiTerminalFlush(pW)刷新渲染
int xuiTerminalClear(pW)清屏
int xuiTerminalSetScrollbackLimit(pW, iLimit)滚动缓冲行数
int xuiTerminalSetFont(pW, pFont)等宽字体
int xuiTerminalSetMetrics(pW, fCellW, fCellH, fPad)单元格尺寸
int xuiTerminalSetColors(pW, iBg, iFg, iCursor, ...)颜色配置
int xuiTerminalResize(pW, iCols, iRows)调整尺寸
int xuiTerminalSetInputCallback(pW, onData, pUser)输入回调

编译本章示例

gcc -O2 -I. -o ch178.exe ch178_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch178.exe

示例:创建嵌入式终端

xui_terminal_desc_t desc = { 0 };

xui_widget pTerm;
xuiTerminalCreate(pCtx, &pTerm, &desc);

// 等宽字体
xuiTerminalSetFont(pTerm, pMonoFont);

// 80×24 标准终端
xuiTerminalResize(pTerm, 80, 24);

// 暗色主题
xuiTerminalSetColors(pTerm,
    0x1E1E1EFF, 0xD4D4D4FF, 0x569CD6FF,
    0x264F78FF, 0xFFFFFFFF, 0xFFFF00FF,
    0x007ACCFF, 0x4FC1FFFF);

// 滚动缓冲 5000 行
xuiTerminalSetScrollbackLimit(pTerm, 5000);

// 写入欢迎信息
xuiTerminalWriteText(pTerm, "XGE Terminal v2.0\r\n");
xuiTerminalFlush(pTerm);

xuiWidgetAddChild(pDock, pTerm);

完整代码

将以下代码保存为 ch178_main.c,编译后运行即可看到一个嵌入式终端模拟器:

#include "xge.h"
#include "xui.h"

static xui_context g_pCtx;
static xui_widget g_pTerm;

static void onTermInput(const char* pData, int iSize, void* pUser) {
    (void)pUser;
    // 回显用户输入
    xuiTerminalWrite(g_pTerm, pData, iSize);
    xuiTerminalFlush(g_pTerm);
}

static int onFrame(void* pUser) {
    (void)pUser;
    xgeClear(0x1E1E1EFF);
    xui_vec2_t pos;
    xgeMouseGet(&pos.x, &pos.y);
    xuiInputPointerMove(g_pCtx, pos.x, pos.y);
    if (xgeMouseDown(XGE_MOUSE_LEFT))
        xuiInputPointerDown(g_pCtx, pos.x, pos.y, 0);
    else
        xuiInputPointerUp(g_pCtx, pos.x, pos.y, 0);
    xuiUpdate(g_pCtx, xgeGetDelta());
    xuiLayout(g_pCtx);
    xuiRender(g_pCtx, NULL, NULL, 0);
    return XGE_OK;
}

int main(void) {
    xge_desc_t d = { 0 };
    d.iWidth = 800; d.iHeight = 600;
    d.sTitle = "ch178 - Terminal";
    d.iFlags = XGE_INIT_VSYNC;
    xgeInit(&d);

    xuiCreate(&g_pCtx);
    extern const xui_proxy_t tXgeProxy;
    xui_proxy_t tXgeProxy = xuiProxyXge();
xuiSetProxy(g_pCtx, &tXgeProxy);
    xuiSetViewportSize(g_pCtx, 800, 600);

    // 创建终端
    xui_terminal_desc_t desc = { 0 };
    xuiTerminalCreate(g_pCtx, &g_pTerm, &desc);

    // 80×24 标准终端
    xuiTerminalResize(g_pTerm, 80, 24);

    // 暗色主题
    xuiTerminalSetColors(g_pTerm,
        0x1E1E1EFF, 0xD4D4D4FF, 0x569CD6FF,
        0x264F78FF, 0xFFFFFFFF, 0xFFFF00FF,
        0x007ACCFF, 0x4FC1FFFF);

    // 滚动缓冲 5000 行
    xuiTerminalSetScrollbackLimit(g_pTerm, 5000);

    // 输入回调
    xuiTerminalSetInputCallback(g_pTerm, onTermInput, NULL);

    // 写入欢迎信息
    xuiTerminalWriteText(g_pTerm, "XGE Terminal v2.0\r\n");
    xuiTerminalWriteText(g_pTerm, "Type something...\r\n");
    xuiTerminalFlush(g_pTerm);

    xui_widget pRoot = xuiGetRootWidget(g_pCtx);
    xuiWidgetAddChild(pRoot, g_pTerm);
    xuiWidgetSetRect(g_pTerm, (xui_rect_t){0, 0, 800, 600});

    xgeRun(onFrame, NULL);
    xuiDestroy(g_pCtx);
    xgeUnit();
    return 0;
}

代码讲解

  • xuiTerminalCreate:创建终端控件,desc 可配置初始行列数等。
  • Resize(80,24):标准终端尺寸,单元格数而非像素。
  • SetColors:配置背景/前景/光标/选区等颜色。
  • SetInputCallback:用户键入时回调触发,可实现回显或转发给子进程。
  • WriteText + Flush:写入文本后必须 Flush 才会渲染到屏幕。

要点与陷阱

  • Flush:Write 后需 Flush 才会渲染,批量写入时最后统一 Flush。
  • ANSI:支持 ESC[ 序列,包括颜色/粗体/下划线/光标定位。
  • CellWidth:SetMetrics 的 CellWidth 需匹配等宽字体实际宽度。
  • Scrollback:过大的 Scrollback 占用内存,建议 1000-10000。

进阶练习

  1. ANSI 颜色测试:输出 256 色调色板验证渲染。
  2. 日志查看器:将应用日志实时写入 Terminal 显示。
Terminal 终端基础效果
图:Terminal 终端基础渲染效果