aboutsummaryrefslogtreecommitdiff
path: root/TUI/unix.jai
blob: 439447df6cf224356def8e6a72e4c5332be5d308 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#import "POSIX";


    __term : My_Termios;

    My_Termios :: struct {
        c_iflag : u32;      // Input mode flags.
        c_oflag : u32;      // Output mode flags.
        c_cflag : u32;      // Control modes flags.
        c_lflag : u32;      // Local modes flags.
        c_line : u8;        // Line discipline.
        c_cc : [32]u8;      // Control characters.
        c_ispeed : u32;     // Input speed (baud rates).
        c_ospeed : u32;     // Output speed (baud rates).
    }

    // Required to do unlocking input.
    libc :: #system_library "libc";

    // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcsetattr.c.html
    tcsetattr :: (fd : s32, optional_actions : s32, termios_p : *My_Termios) -> s32 #foreign libc;

    // https://codebrowser.dev/glibc/glibc/sysdeps/unix/sysv/linux/tcgetattr.c.html
    tcgetattr :: (fd : s32, termios_p : *My_Termios) -> s32 #foreign libc;
    

OS_prepare_terminal :: () {
    // TODO Required to do unlocking input.
    tcgetattr(STDIN_FILENO, *__term);
    term_new := __term;

    term_new.c_iflag &= 0xFFFFFA14;// ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    term_new.c_oflag &= 0xFFFFFFFE;// ~OPOST;
    term_new.c_lflag &= 0xFFFF7FB4;// ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    term_new.c_cflag &= 0xFFFFFECF;// ~(CSIZE | PARENB);
    term_new.c_cflag |= 0x00000030;

    tcsetattr(STDIN_FILENO, 0, *term_new);
}

OS_reset_terminal :: () {
    tcsetattr(STDIN_FILENO, 0, *__term); // return echo
}

OS_get_terminal_size :: () -> rows: int, columns: int {
    buffer: [512] u8;
    write_string(Commands.QueryWindowSizeInChars);
    bytes_read := read(STDIN_FILENO, buffer.data, buffer.count-1);

    str := to_string(buffer.data, bytes_read);

    // Result: [8;79;156t
    assert(
        buffer.data[0] == #char "\e" &&
        buffer.data[1] == #char "[" &&
        buffer.data[2] == #char "8",
        "Query windows size in chars returned invalid response.");

    parts := split(str, ";");
    rows := parse_int(*parts[1]);
    columns := parse_int(*parts[2]);
    return rows, columns;
}