kotlin/tty/demo_tty.kt · 13049 字节 · 下载原文
// demo_tty.kt —— **第 2 层:彩色命令行**(`tty_*`)
// demo_tty.kt — **Layer 2: colored command line** (`tty_*`)
//
// ⚠ **新程序用 `tty_*`,老程序才用 `conio` / `Crt`**(用户定的分层标准:
// ⚠ **New programs use `tty_*`; only old programs use `conio` / `Crt`** (the layering standard the user set:
// 「新版程序,文字模式用 tty 库,图像模式用 ui 库;旧版老程序才用 conio、graphics 等库」)。
// "new programs use the tty library in text mode and the ui library in graphics mode; only old programs use conio, graphics and the like").
// `tty_*` 只有字符、没有任何图形功能;要画图用 BGI 或 `ui_*`。
// `tty_*` is characters only, with no graphics capability whatsoever; to draw, use BGI or `ui_*`.
// 坐标 **1 起算**、颜色 **0–15 索引色**。
// Coordinates are **1-based**; colors are **indexed 0–15**.
//
// ## ✅ 本份**现在能跑**(2026-10-04 复验)—— 此前那条「跑不起来」已作废
// ## ✅ This one **runs now** (re-verified 2026-10-04) -- the old "does not run" note is void
//
// 此前这里写着「本份**当前跑不起来** —— 链不上 `tty.vml`(两件事,都在这份例程之外)」。
// This section used to say "this one **does not currently run** -- it cannot link `tty.vml` (two things, both outside this example)".
// 那**两件事现在都修好了**:
// **Both** of those are now fixed:
//
// ① ~~`Libs=` 里没有 `tty.vml`~~ —— 已修:`vmltool.config.xml` 的 kotlin 那行现在是
// ① ~~`tty.vml` is not in `Libs=`~~ -- fixed: the kotlin line in `vmltool.config.xml` is now
// `<Language Name="kotlin" Libs="vmlui.vml,vml3d.vml,tty.vml,mathd.vml" />`,`tty.vml` 已经挂上。
// `<Language Name="kotlin" Libs="vmlui.vml,vml3d.vml,tty.vml,mathd.vml" />`, so `tty.vml` is hooked up.
//
// ② ~~`--lib` 与 `Libs=` 对 Kotlin 根本不生效(`KotlinCompiler.Compile` 里那次
// ② ~~`--lib` and `Libs=` had no effect at all for Kotlin (the pre-link
// `LinkStandardLibrary(prog,"kotlin",null)` 抢先把 `tty_*` 判成「未定义的函数」硬错误抛出)~~ ——
// `LinkStandardLibrary(prog,"kotlin",null)` inside `KotlinCompiler.Compile` failed `tty_*` as a hard "undefined function" first)~~ --
// 已修:那次预链接**已经删掉**(`KotlinCompiler.cs` 里那段注记就是这次改动的记录),
// fixed: that pre-link **has been removed** (the comment in `KotlinCompiler.cs` records the change),
// 而且 `import X` 现在是「**再加一个库**」而不是「顶替这门语言的默认库集」(`CompilerHelper.cs` 的注记)。
// and `import X` now **adds a library** rather than replacing the language's default set (note in `CompilerHelper.cs`).
//
// 实测(2026-10-04):
// Measured (2026-10-04):
// · `vmlcli Examples/kotlin/tty/demo_tty.kt` => ✔ 编译完成(60796 条指令)并**运行到底**
// · `vmlcli Examples/kotlin/tty/demo_tty.kt` => ✔ compiles (60796 instructions) and **runs to completion**
// (画出标题栏 / ASCII 面板 / UTF-8 单线框 / 16 色色带 / 状态栏)。
// (draws the title bar / ASCII panel / UTF-8 single-line frame / 16-color bar / status bar).
// · `import vmlui.*` + `tty_goto(...)` 也编得过(59379 条指令,与不写 import 相同)。
// · `import vmlui.*` + `tty_goto(...)` also compiles (59379 instructions, the same as with no import).
//
// ⚠ 当年那条「别用 C 风格 `external` 声明去绕」(紧跟着的第一个 `fun` 会被当成外部函数编译、丢函数体)也**已修**:
// ⚠ The old "don't work around it with a C-style `external` declaration" note (the next `fun` was compiled as external, dropping its body) is **also fixed**:
// 实测 `external int tty_init(int w,int h,int c);` + `fun foo(): Int { return 42 }` + `fun main(){ print(foo()) }` 打出 **42**;
// measured `external int tty_init(int w,int h,int c);` + `fun foo(): Int { return 42 }` + `fun main(){ print(foo()) }` prints **42**;
// 连 `external ...;` 后紧跟 `fun main(){ print("main-ran\n") }` 也照常打印(不再有"静默空跑")。
// even `external ...;` followed by `fun main(){ print("main-ran\n") }` prints as usual (no more "silent no-op").
//
// ## 本文件的状态:**写法与运行都已验证**(2026-10-04)
// ## Status of this file: **style AND running both verified** (2026-10-04)
//
// · 版面与调用串和 `Examples/kotlin/demo_ui.kt` 同一套、与 `Examples/java/demo_tty.java` **逐句同构**。
// · The layout and call sequences are the same set as `Examples/kotlin/demo_ui.kt` and **sentence-for-sentence isomorphic** to `Examples/java/demo_tty.java`.
// · Kotlin 这边现在**整份编得过、跑得出画面**(指令数 60796)。
// · On the Kotlin side it now **compiles as a whole and draws the screen** (60796 instructions).
//
// ## ⚠ UTF-8 的字节预算
// ## ⚠ The UTF-8 byte budget
//
// `conio.c` 的 `putch()` 把**字节**当**列**计数(到 80 折行),一个汉字/框线字符 3 字节
// `putch()` in `conio.c` counts **bytes** as **columns** (wrapping at 80), and one Chinese character / box-drawing char is 3 bytes
// ⇒ 某段连续输出跨过第 80 列时折行落在字符中间,宿主按字节重组 UTF-8 的校验随即失败
// ⇒ when a continuous run of output crosses column 80 the wrap lands mid-character, the host's byte-wise UTF-8 reassembly check then fails
// 并**粘性**切成单字节老编码 ⇒ 之后整份输出全乱。版面遵守「起始列 + 3×字符数 ≤ 80」。
// and **stickily** switches to a single-byte legacy encoding ⇒ everything after that is garbled. The layout obeys "start column + 3×chars ≤ 80".
// 细节与最小复现见 `Examples/c/demo_tty.c` 文件头。
// For details and a minimal reproduction see the header of `Examples/c/demo_tty.c`.
// ── 显式引用:`tty_*` 来自 tty.vml,`ui_*` 来自共享库 vmlui.vml ──────────
// ── Explicit reference: `tty_*` comes from tty.vml, `ui_*` from the shared library vmlui.vml ──
// `tty_` **不在**前端的符号前缀表里,靠 `vmltool.config.xml` 的
// `tty_` is **not** in the frontend's symbol-prefix table; it links via
// `<Language Name="kotlin" Libs="vmlui.vml,vml3d.vml,tty.vml,mathd.vml" />` 进链。
// `<Language Name="kotlin" Libs="vmlui.vml,vml3d.vml,tty.vml,mathd.vml" />`.
// ⚠ ~~一旦写了 import,语言的默认库集就不再补进来(实测:只写 `import vmlui.*` ⇒ `tty.vml` 一次都没被链接,报 8 条「未定义的函数 'tty_*'」)~~
// ⚠ ~~once any import exists, that default set is no longer added (measured: with only `import vmlui.*` the linker never pulls `tty.vml`, failing with 8 "undefined function 'tty_*'")~~
// —— 2026-10-04 复验**已修**:`import X` 是「再加一个库」而不是「顶替默认库集」,
// -- **fixed**, re-verified 2026-10-04: `import X` "adds a library" and does not replace the default set;
// 实测只写 `import vmlui.*` + `tty_goto(...)` 也编得过(59379 条指令,与不写 import 相同)。
// measured: `import vmlui.*` + `tty_goto(...)` compiles (59379 instructions, the same as with no import).
// ⚠ `.*` 必须有:`import tty`(无 `.*`)会被 `ExtractImports` 的正则静默忽略。
// ⚠ The `.*` is required: `import tty` (without `.*`) is silently ignored by `ExtractImports`.
#include "../../../Lib/kotlin/vml_ui.kt"
import tty.*
import vmlui.*
// 在第 (x,y) 处用指定前景/背景打一串
// Print a string at (x,y) with the given foreground/background
fun say(x: Int, y: Int, fg: Int, bg: Int, s: String) {
tty_print_at(x, y, s, fg, bg)
}
fun main() {
var i = 0
// 界面语言:开局查一次(`ui_scr_get_language` 是 syscall,别每处都调)
// UI language: queried once at start (`ui_scr_get_language` is a syscall, do not call it everywhere)
var lang = ui_scr_get_language()
// ⚠ 分支写成**单行 `if/else`** —— **C 风格三目 `cond ? a : b` 仍不能用**(2026-10-04 复验:实参位置静默错编);
// ⚠ Branches are written as a **one-line `if/else`** -- the **C-style ternary `cond ? a : b` still cannot be used** (re-verified 2026-10-04: silently miscompiles in argument position);
// 而 Kotlin 的 Elvis `?:` **已经能用**(本份没用到)。
// Kotlin's Elvis `?:` **works now** (not used in this file).
// ── 1. 初始化 + 清屏 ──
// ── 1. Init + clear screen ──
tty_init(0, 0, 0)
tty_cls()
// ── 2. 标题栏:亮黄字 + 蓝底,铺满第 1 行 ──
// ── 2. Title bar: bright yellow on blue, filling row 1 ──
tty_color(14, 1)
tty_goto(1, 1)
tty_puts(" ")
tty_goto(3, 1)
tty_puts("Dolaima tty_* demo (Kotlin) -- color / cursor / box / int")
tty_color(8, 0)
tty_goto(3, 2)
tty_puts("tty.h: tty_init / tty_cls / tty_color / tty_goto / tty_box / tty_put_int")
// ── 3. ASCII 面板(61 列,安全)──
// ── 3. ASCII panel (61 columns, safe) ──
tty_color(7, 0)
tty_box(2, 3, 62, 12, 0) // style 0 = ASCII(`+ - |`)
// 面板里的内容:每行一种前景色
// Panel contents: one foreground color per line
if (lang == 0) { say(4, 4, 7, 0, "color 7 lightgray 普通正文") } else { say(4, 4, 7, 0, "color 7 lightgray body text") }
if (lang == 0) { say(4, 5, 11, 0, "color 11 lightcyan 次要信息") } else { say(4, 5, 11, 0, "color 11 lightcyan secondary") }
if (lang == 0) { say(4, 6, 10, 0, "color 10 lightgreen ok / 成功") } else { say(4, 6, 10, 0, "color 10 lightgreen ok / success") }
if (lang == 0) { say(4, 7, 14, 0, "color 14 yellow 状态栏高亮") } else { say(4, 7, 14, 0, "color 14 yellow status bar") }
if (lang == 0) { say(4, 8, 12, 0, "color 12 lightred 错误 / 警告") } else { say(4, 8, 12, 0, "color 12 lightred error / warn") }
if (lang == 0) { say(4, 9, 13, 0, "color 13 lightmagenta 强调") } else { say(4, 9, 13, 0, "color 13 lightmagenta emphasis") }
// 反白一行("选中项"的长相):黑字白底
// Reverse-video one line (what a "selected item" looks like): black on white
say(4, 11, 0, 7, " > Open (reversed: fg=0 bg=7) ")
// ── 4. UTF-8 单线框(19 格宽 × 3 字节 = 57,从第 4 列起 ⇒ 61 字节,安全)──
// ── 4. UTF-8 single-line frame (19 cells wide × 3 bytes = 57, starting at column 4 ⇒ 61 bytes, safe) ──
tty_color(11, 0)
tty_box(4, 14, 22, 19, 1) // style 1 = ┌ ─ │ ┐ └ ┘ 单线框
// style 1 = single-line box ┌ ─ │ ┐ └ ┘
if (lang == 0) { say(6, 16, 14, 0, "中文也") } else { say(6, 16, 14, 0, "CJK too") }
if (lang == 0) { say(6, 17, 10, 0, "没问题") } else { say(6, 17, 10, 0, "works") }
// ── 5. 右侧说明(ASCII,列 26 起)──
// ── 5. Right-hand notes (ASCII, starting at column 26) ──
say(26, 14, 11, 0, "tty_box(..., style=1)")
say(26, 15, 7, 0, " = UTF-8 single-line box")
say(26, 17, 11, 0, "tty_box(..., style=0)")
say(26, 18, 7, 0, " = ASCII box (used above)")
// ── 6. 16 色色带 ──
// ── 6. 16-color bar ──
i = 0
while (i < 16) {
tty_color(0, i)
tty_goto(3 + i * 4, 21)
tty_puts(" ")
i = i + 1
}
tty_color(7, 0)
tty_goto(3, 22)
tty_puts("index 0..15: black blue green cyan red magenta brown gray / +8 = bright")
// ── 7. 数字与光标 ──
// ── 7. Numbers and the cursor ──
tty_color(11, 0)
tty_goto(3, 24)
tty_puts("tty_put_int: ")
tty_color(14, 0)
tty_put_int(2026)
tty_color(11, 0)
tty_puts(" / ")
tty_color(14, 0)
tty_put_int(-42)
tty_color(11, 0)
tty_puts(" cursor=")
tty_put_int(tty_wherex())
tty_puts(",")
tty_put_int(tty_wherey())
tty_puts(" screen=")
tty_put_int(tty_width())
tty_puts("x")
tty_put_int(tty_height())
// ── 8. 状态栏 + 收尾 ──
// ── 8. Status bar + wrap-up ──
tty_color(0, 3)
tty_goto(1, 24)
tty_puts(" tty_* demo done -- no key wait, exits by itself ")
tty_color(8, 0)
tty_goto(3, 25)
if (lang == 0) { tty_puts("demo_tty (Kotlin) 结束 —— 画完即退出") } else { tty_puts("demo_tty (Kotlin) done -- draws and exits") }
tty_color(7, 0)
}