← 都来码 / Dolaima← 例程索引kotlin/tty/demo_tty.kt原文

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)
}