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

java/tty/demo_tty.java · 10329 字节 · 下载原文

// demo_tty.java —— **第 2 层:彩色命令行**(`tty_*`)

// demo_tty.java — **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**.

//

// ## ⚠ Java 调库必须 `static native` 声明

// ## ⚠ Java library calls must be declared `static native`

//

// `asm()` 已从 Java 前端移除(`CodeGenerator.Expressions.cs` 注明「仅限 C/ObjC/C++」),

// `asm()` has been removed from the Java frontend (`CodeGenerator.Expressions.cs` notes "C/ObjC/C++ only"),

// 不声明就发 `CALL method_xxx`,链接期找不到标签。声明里的 `String` 对应 C 的 `char*`。

// and without a declaration it emits `CALL method_xxx`, whose label cannot be found at link time. The `String` in the declaration corresponds to C's `char*`.

//

// ## ⚠⚠ 它需要把 `tty.vml` 链进来,而**默认配置没链**

// ## ⚠⚠ It needs `tty.vml` linked in, and **the default configuration does not link it**

//

// 实测(2026-09-24):直接跑报 `<input>:N: error: 未定义的函数 'tty_init'(引用 1 次)`。

// Measured (2026-09-24): running it directly reports `<input>:N: error: undefined function 'tty_init' (referenced 1 time)`.

// `vmltool.config.xml` 里 java(以及所有其它语言)的 `Libs` 只有 `vmlui.vml`,

// In `vmltool.config.xml` the `Libs` of java (and every other language) contains only `vmlui.vml`,

// **新落地的 `tty.vml` 一门语言都没挂上**。C 是唯一例外 —— `Lib/c/tty.h` 里那句

// **the newly added `tty.vml` is hooked to no language at all**. C is the only exception — the

// `#param lib("tty")` 生效了,所以 C 不加参数就能用。

// `#param lib("tty")` in `Lib/c/tty.h` takes effect, so C can use it without extra arguments.

//

//   · 桌面跑法:`vmlcli Examples/java/demo_tty.java --lib Lib/shared/tty.vml`

//   · Desktop: `vmlcli Examples/java/demo_tty.java --lib Lib/shared/tty.vml`

//   · 上手机:要在 `vmltool.config.xml` 给 java 的 `Libs=` 补 `tty.vml`(共享配置,按约定未代改)

//   · On the phone: add `tty.vml` to java's `Libs=` in `vmltool.config.xml` (shared configuration; by convention not changed on your behalf)

//

// ## ⚠ 两条 Java 前端的写法约束(见 demo_std.java 的文件头)

// ## ⚠ Two style constraints of the Java frontend (see the header of demo_std.java)

//

//   · **不能用 `static final int` 常量**:类字段读出来是它的地址不是值

//   · **`static final int` constants cannot be used**: a class field reads back as its address, not its value

//     (`static int A = 9` 读回 1024)。所以下面一处常量都不定义,数字写死。

//     (`static int A = 9` reads back 1024). So not a single constant is defined below; the numbers are hardcoded.

//   · 字符串拼接 `+` 不可用 ⇒ 标签与值分两次 `tty_puts` / `tty_put_int` 写。

//   · String concatenation `+` is unusable ⇒ write the label and the value with two calls, `tty_puts` / `tty_put_int`.

//

// ## ⚠ 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`.


#include "../../../Lib/java/vml_ui.java"
public class DemoTty {

    static native int  tty_init(int width, int height, int clear);
    static native void tty_cls();
    static native void tty_goto(int x, int y);
    static native void tty_color(int fg, int bg);
    static native void tty_puts(String s);
    static native void tty_put_int(int v);
    static native void tty_print_at(int x, int y, String s, int fg, int bg);
    static native void tty_box(int x1, int y1, int x2, int y2, int style);
    static native int  tty_wherex();
    static native int  tty_wherey();
    static native int  tty_width();
    static native int  tty_height();

    static native int  ui_scr_get_language();

    // 在第 (x,y) 处用指定前景/背景打一串

    // Print a string at (x,y) with the given foreground/background

    static void say(int x, int y, int fg, int bg, String s) {
        tty_print_at(x, y, s, fg, bg);
    }

    public static void main(String[] args) {
        int i;
        int lang = ui_scr_get_language();

        // ── 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 (Java)  --  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

        say(4, 4,  7,  0, lang == 0 ? "color  7  lightgray    普通正文" : "color  7  lightgray    body text");
        say(4, 5,  11, 0, lang == 0 ? "color 11  lightcyan    次要信息" : "color 11  lightcyan    secondary info");
        say(4, 6,  10, 0, lang == 0 ? "color 10  lightgreen   ok / 成功" : "color 10  lightgreen   ok / success");
        say(4, 7,  14, 0, lang == 0 ? "color 14  yellow       状态栏高亮" : "color 14  yellow       status bar");
        say(4, 8,  12, 0, lang == 0 ? "color 12  lightred     错误 / 警告" : "color 12  lightred     error / warning");
        say(4, 9,  13, 0, lang == 0 ? "color 13  lightmagenta 强调" : "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 ┌ ─ │ ┐ └ ┘


        say(6, 16, 14, 0, lang == 0 ? "中文也" : "CJK also");
        say(6, 17, 10, 0, lang == 0 ? "没问题" : "works fine");

        // ── 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);
        tty_puts(lang == 0 ? "demo_tty (Java) 结束 —— 画完即退出" : "demo_tty (Java) done -- draws then exits");

        tty_color(7, 0);
    }
}