Selection 选区模型 + Editing 编辑命令:插入/删除/缩进/注释切换/多光标。
CodeEdit 编辑操作分两层:
• Selection Model:管理光标/选区/多光标,支持 SetRange/SelectAll/GotoLineColumn
• Editing:基于 Document+Selection 执行编辑命令(插入/删除/缩进/注释)
所有编辑操作自动维护 Undo/Redo 栈,bReadonly 参数保护只读文档。
| 函数 | 说明 |
|---|---|
int xuiCodeSelectionSetRange(pSel, pDoc, iAnchor, iCaret) | 设置选区范围 |
int xuiCodeSelectionSelectAll(pSel, pDoc) | 全选 |
int xuiCodeSelectionSelectWord(pSel, pDoc, iOffset) | 选中单词 |
int xuiCodeSelectionGotoLineColumn(pSel, pDoc, iLine, iCol, bExtend) | 跳转行列 |
int xuiCodeSelectionMove(pSel, pDoc, iCommand) | 方向移动 |
int xuiCodeEditingInsertText(pDoc, pSel, sText, bReadonly) | 插入文本 |
int xuiCodeEditingDeleteBackward(pDoc, pSel, bReadonly) | 退格删除 |
int xuiCodeEditingDeleteForward(pDoc, pSel, bReadonly) | 前向删除 |
int xuiCodeEditingIndentSelection(pDoc, pSel, sIndent, bReadonly) | 增加缩进 |
int xuiCodeEditingOutdentSelection(pDoc, pSel, iCols, bReadonly) | 减少缩进 |
int xuiCodeEditingToggleLineComment(pDoc, pSel, sComment, bReadonly) | 切换行注释 |
gcc -O2 -I. -o ch175.exe ch175_main.c src\xui_*.c build\xge.lib -lm -lws2_32 -liphlpapi -lgdi32 -luser32 -lshell32 -lopengl32 -lole32 -lwinmm -lavrt
.\ch175.exe
xui_code_document pDoc = xuiCodeEditGetDocument(pEditor);
xui_code_selection_model pSel = xuiCodeEditGetSelection(pEditor);
// 跳转到第 10 行第 1 列
xuiCodeSelectionGotoLineColumn(pSel, pDoc, 10, 1, 0);
// 插入文本(自动 Undo)
xuiCodeEditingInsertText(pDoc, pSel, "#include <stdio.h>\n", 0);
// 选中第 5-8 行并增加缩进
xuiCodeSelectionGotoLineColumn(pSel, pDoc, 5, 1, 0);
xuiCodeSelectionGotoLineColumn(pSel, pDoc, 8, 1, 1); // bExtend=1
xuiCodeEditingIndentSelection(pDoc, pSel, " ", 0);
// 切换行注释 (C 风格)
xuiCodeEditingToggleLineComment(pDoc, pSel, "//", 0);
// 确保光标可见
xuiCodeEditEnsureCaretVisible(pEditor);将以下代码保存为 ch175_main.c,编译后运行即可看到编程式插入/缩进/注释效果:
#include "xge.h"
#include "xui.h"
static xui_context g_pCtx;
static xui_widget g_pEditor;
static int g_bDone = 0;
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);
// 首帧执行编程式编辑
if (!g_bDone) {
g_bDone = 1;
xui_code_document pDoc = xuiCodeEditGetDocument(g_pEditor);
xui_code_selection_model pSel = xuiCodeEditGetSelection(g_pEditor);
// 跳到第 3 行插入代码
xuiCodeSelectionGotoLineColumn(pSel, pDoc, 3, 1, 0);
xuiCodeEditingInsertText(pDoc, pSel,
" int x = 42;\n", 0);
// 选中第 2-4 行并增加缩进
xuiCodeSelectionGotoLineColumn(pSel, pDoc, 2, 1, 0);
xuiCodeSelectionGotoLineColumn(pSel, pDoc, 4, 1, 1);
xuiCodeEditingIndentSelection(pDoc, pSel, " ", 0);
// 切换行注释
xuiCodeEditingToggleLineComment(pDoc, pSel, "//", 0);
xuiCodeEditEnsureCaretVisible(g_pEditor);
}
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 = 900; d.iHeight = 640;
d.sTitle = "ch175 - Editing Ops";
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, 900, 640);
xui_code_edit_desc_t desc = { 0 };
xuiCodeEditCreate(g_pCtx, &g_pEditor, &desc);
xuiCodeEditSetLanguage(g_pEditor, "c");
xuiCodeEditSetDefaultMargins(g_pEditor, 1, 0, 0, 0);
const char* sCode =
"#include <stdio.h>\n"
"int main(void) {\n"
" return 0;\n"
"}\n";
xuiCodeEditSetText(g_pEditor, sCode);
xui_widget pRoot = xuiGetRootWidget(g_pCtx);
xuiWidgetAddChild(pRoot, g_pEditor);
xuiWidgetSetRect(g_pEditor, (xui_rect_t){0, 0, 900, 640});
xgeRun(onFrame, NULL);
xuiDestroy(g_pCtx);
xgeUnit();
return 0;
}