Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,10 @@ add_executable(decawm_mode_test experiments/core/decawm_mode_test.cpp)
target_link_libraries(decawm_mode_test PRIVATE termforge_core)
termforge_warnings(decawm_mode_test)

add_executable(order_query_test experiments/core/order_query_test.cpp)
target_link_libraries(order_query_test PRIVATE termforge_core)
termforge_warnings(order_query_test)

add_executable(paste_test experiments/shell/paste_test.cpp)
termforge_warnings(paste_test)
add_executable(clipboard_policy_test experiments/shell/clipboard_policy_test.cpp)
Expand Down Expand Up @@ -307,6 +311,8 @@ if(BUILD_TESTING)
add_test(NAME alternate_mode_core COMMAND alternate_mode_test)
add_test(NAME decawm_mode_core COMMAND decawm_mode_test)
set_tests_properties(decawm_mode_core PROPERTIES TIMEOUT 10)
add_test(NAME order_query_core COMMAND order_query_test)
set_tests_properties(order_query_core PROPERTIES TIMEOUT 10)
add_test(NAME paste COMMAND paste_test)
add_test(NAME clipboard_policy COMMAND clipboard_policy_test)
add_test(NAME keyboard COMMAND keyboard_test)
Expand Down
1 change: 1 addition & 0 deletions docs/EVIDENCE.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
| 配置 | 证据定位 |
|---|---|
| 自主 C++ 主屏 ASCII DECAWM | [有限合同与红绿](../experiments/core/results/2026-10-29-cpp-decawm/README.md)、[固定验证身份](../experiments/core/results/2026-10-29-cpp-decawm/validation.json):抽取原版14–18阶段79B,strict/recovery各235个字面前缀分块用例;初次定向8/9的缺构建依赖失败、补建后的core单项31测试通过分列。跨1049/宽字/resize、origin/margin、GUI/固定ConPTY运输和完整TUI均不由本项验收 |
| 自主 C++ 行结构发布与精确身份查询 | [首片合同与固定夹具](../experiments/core/results/2026-10-29-order-query/README.md)、[验证身份](../experiments/core/results/2026-10-29-order-query/validation.json):`[1,3,4,5,7,6]` 的精确 rank(7→4、6→5、2 缺失)、文档序比较与强制 Find 导航、结构 revision 边界、发布拒绝与光标夹取;筛选的 8 项核心 CTest 与本地候选 `candidate_core` 通过,首个推送版本的 CI 红(回放保留历史仍为上一帧宽度)与按物理行策略适配后的绿分列,完整默认 Release 构建 exit0。未封住公开 lines/history,运行中跨重排的增量 Find、区域 LF、Qt/固定 ConPTY 与性能均未验收 |
| 自主 C++ 限定 1049 协议 | [固定结果](../experiments/core/results/2026-10-29-cpp-1049/README.md)、[验证身份](../experiments/core/results/2026-10-29-cpp-1049/validation.json):文字/光标/颜色及 pending-wrap、重复进入与读者失效;55项中Qt1项分列,13条内部skip及旧负例判据失败保留。未验收非颜色属性/全网格背景、其他模式、真实TUI/IME/DPI、呈现或性能 |
| 自主 C++ 双缓冲存储与文档 epoch 基础 | [固定结果](../experiments/core/results/2026-10-29-buffer-state-r2/README.md)、[验证身份](../experiments/core/results/2026-10-29-buffer-state-r2/validation.json):拥有状态、共享 ID、隐藏帧 resize 回滚与跨缓冲句柄失效;Qt/candidate 关闭配置的完整 50 项及 12 条内部 skip 分列。未接 private CSI,不是原版模式、Qt 产品路线或完整 #27 验收 |
| Qt 基础 Unicode 文本字节 | [红绿与联合验证](../experiments/shell/results/2026-10-29-qt-unicode-input/README.md)、[固定联合身份](../experiments/shell/results/2026-10-29-qt-unicode-input/validation.json):公开Qt事件到独立ReadConsoleW接收端,整/分事件代理项、焦点/隐藏/关闭、1024B整包与NUL、两目标隔离。2b6d源码一次61项分列Qt3/其余58,13内部skip、旧红例与27原件保留;不是实际IME、字素/字形、原生Unicode窗口、DPI或性能验收 |
Expand Down
2 changes: 1 addition & 1 deletion docs/FEATURES.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
|---|---|---|---|
| 自主 C++ / Qt / 固定微软 ConPTY | **实现中,未验收**:[显式 Qt 入口](../src/qt/README.md)提供默认 80×24、随可用区域变化的 cmd 标签、基本 ASCII 与[限定 Unicode 文本字节](../experiments/shell/results/2026-10-29-qt-unicode-input/README.md)、16 色及各会话独立有界队列;[基础动态尺寸验证](../experiments/shell/results/2026-10-29-qt-resize/README.md)分离窗口/核心/transport 与真实 child,覆盖极小、重复、隐藏页和关闭交叉,并复验原标签算术及事件循环回收。678 原生极窄失败保留;0ff 仅修订字面子区域/顶层实际区域夹具,另有[冻结包一次隔离原生成功](../experiments/shell/results/2026-10-29-qt-resize/native-validation.json):实际顶层区域、core/transport/child 一致,窗口仅 DPI 96。旧尺寸结果保留各自源码;[Unicode 联合源码的一次完整61项](../experiments/shell/results/2026-10-29-qt-unicode-input/validation.json)分开 Qt3项与其余58项既有/独立诊断,13条内部skip保留 | 分屏、其他 shell、工作区恢复、完整 resize/reflow、历史/选择/Find、完整 Unicode 字素/绘制与 IME、真实 DPI、应用兼容与性能仍需实现或迁移;物理裁剪不恢复丢弃正文,完整 WindTerm 标签/尺寸行为对照未完成;当前不是可发布开发包 | R2 |

自主 C++ 核心已有 [#130 双缓冲存储基础](../experiments/core/results/2026-10-29-buffer-state-r2/README.md),并接入 [#135 限定 1049 协议](../experiments/core/results/2026-10-29-cpp-1049/README.md):strict/recovery 识别 `?1049h/l`,重复进入归首格、清旧备用文本和复位写入颜色,返回恢复主屏文字/光标/颜色及 pending-wrap。共享行 ID、双帧物理 resize 与逻辑 epoch 防止旧位置、选择、搜索及 viewport 复活,包括清屏后重写相同文字。[主屏 ASCII DECAWM 切片 #161](../experiments/core/results/2026-10-29-cpp-decawm/README.md)另按[有限直接观察](research/windterm-origin-wrap-reference-2026-10-29.md)实现 `?7h/l` 与末列开关,验证五阶段79B的字面文字/位置及分块;原版 origin/margin、wrap跨屏/宽字/resize和完整网格/样式仍未知或未实现。#135本地55项中Qt1项与其余54项诊断分列,13条内部跳过保留;#161仅有独立core CLI定向回归,不表示完整 [#27](https://github.com/JavaZeroo/termforge/issues/27)、真实 TUI/Qt 交互或系统剪贴板已验收。
自主 C++ 核心已有 [#130 双缓冲存储基础](../experiments/core/results/2026-10-29-buffer-state-r2/README.md),并接入 [#135 限定 1049 协议](../experiments/core/results/2026-10-29-cpp-1049/README.md):strict/recovery 识别 `?1049h/l`,重复进入归首格、清旧备用文本和复位写入颜色,返回恢复主屏文字/光标/颜色及 pending-wrap。共享行 ID、双帧物理 resize 与逻辑 epoch 防止旧位置、选择、搜索及 viewport 复活,包括清屏后重写相同文字。[主屏 ASCII DECAWM 切片 #161](../experiments/core/results/2026-10-29-cpp-decawm/README.md)另按[有限直接观察](research/windterm-origin-wrap-reference-2026-10-29.md)实现 `?7h/l` 与末列开关,验证五阶段79B的字面文字/位置及分块;原版 origin/margin、wrap跨屏/宽字/resize和完整网格/样式仍未知或未实现。#135本地55项中Qt1项与其余54项诊断分列,13条内部跳过保留;#161仅有独立core CLI定向回归,不表示完整 [#27](https://github.com/JavaZeroo/termforge/issues/27)、真实 TUI/Qt 交互或系统剪贴板已验收。另有[行结构发布与精确身份查询首片 #169](../experiments/core/results/2026-10-29-order-query/README.md):`Screen` 经 `publish` 提交拥有值的行镜像并推进结构 revision,`locate` 精确回答 ID→rank(缺失不落到邻行),`TextDocument` 的定位/比较与 `HistoryViewport` 的活 anchor 改用精确 rank,`TextSearch` 只把**导航比较**改成文档序;固定 `[1,3,4,5,7,6]` 夹具、筛选的 8 项核心 CTest 与候选 `candidate_core` 通过(首个推送版本在该项为红,混合宽度帧修复后复跑为绿,过程保留)。该片**未**封住公开 `lines/history`、未迁移有序增量 Find 的 `emit/prune/rewind` ID 假设,也没有区域 LF、新 VT 或 Qt/固定 ConPTY 证据;#169 与 #27/#29 保持开放。

Qt 构建显式准备并部署[固定微软 CRT 14.51.36247.0](../third_party/msvc_runtime/README.md),不安装到 System32。隔离 Windows 的[限定加载与 cmd 验证](../experiments/shell/results/2026-10-29-qt-crt-deploy/README.md)保留原包失败、原 52 文件不变且仅追加 CRT/原许可后的成功,以及新源码包的独立验证;它不解除完整产品打包、Qt/第三方分发审计、实际 DPI/IME 或物理呈现的验收缺口。

Expand Down
18 changes: 14 additions & 4 deletions experiments/core/candidate_terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,7 @@ void CandidateTerminal::synchronize() {
screen.wrap_pending = replay_origin_->wrap_pending;
screen.discarded = replay_origin_->discarded;
screen.style = replay_origin_->style;
screen.history = replay_origin_->history;
screen.lines = replay_origin_->lines;
screen.restore_frame(*replay_origin_);
}
return;
}
Expand Down Expand Up @@ -343,13 +342,24 @@ void CandidateTerminal::synchronize() {
versions.emplace(line.id, version);
}

// Preserved history arrives from an older frame, so it can still hold the
// previous width. Fit it with the same physical-row policy Screen::resize
// applies instead of publishing rows whose width contradicts the frame.
for (auto& line : retained) {
if (line.size() == static_cast<size_t>(meta.columns)) continue;
if (line.size() > static_cast<size_t>(meta.columns)) line.cropped = true;
line.resize(meta.columns);
if (!line.empty() && line.back().width == 2) line.back() = Cell{};
}
screen.publish(std::vector<Line>(retained.begin(), retained.begin() + meta.history),
std::vector<Line>(retained.begin() + meta.history, retained.end()));
// Cursor and style follow the accepted publication: a rejected frame must
// not leave the screen half-updated.
screen.row = meta.row;
screen.column = static_cast<int>(meta.column);
screen.wrap_pending = meta.wrap_pending;
screen.discarded = meta.discarded;
screen.style = {meta.fg, meta.bg, meta.bold};
screen.history.assign(retained.begin(), retained.begin() + meta.history);
screen.lines.assign(retained.begin() + meta.history, retained.end());
versions_ = std::move(versions);
identity_aliases_.clear();
for (size_t index = 0; index < retained.size(); ++index)
Expand Down
12 changes: 9 additions & 3 deletions experiments/core/history_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,16 @@ class HistoryViewport {
}
public:
// A viewport is owned by exactly one session. Never share it across Screens.
// A live anchor uses its exact rank; an evicted anchor keeps the existing
// ordered-history fallback (first retained row at or after the id).
size_t anchor_top(const Screen& screen) const {
if (const auto index = screen.locate(anchor_)) return (std::min)(*index, screen.history.size());
return (std::min)(screen.lower_bound_line(anchor_), screen.history.size());
}
ViewportState reconcile(const Screen& screen) {
sync_epoch(screen);
const size_t maximum = screen.history.size();
const size_t top = following_ ? maximum : (std::min)(screen.lower_bound_line(anchor_), maximum);
const size_t top = following_ ? maximum : anchor_top(screen);
anchor_ = screen.retained_line(top).id;
return {top, screen.retained_size(), static_cast<size_t>(screen.height()), maximum, anchor_, following_};
}
Expand All @@ -53,8 +59,8 @@ class HistoryViewport {
}
ViewportState bottom(const Screen& screen) { return scroll_to(screen, screen.history.size()); }
ViewportState reveal(const Screen& screen, uint64_t identity) {
const auto index = screen.lower_bound_line(identity);
return scroll_to(screen, index);
if (const auto index = screen.locate(identity)) return scroll_to(screen, *index);
return scroll_to(screen, screen.lower_bound_line(identity));
}
bool following() const { return following_; }
uint64_t anchor() const { return anchor_; }
Expand Down
Loading