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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
|
use fmt;
use tb = termbox2;
def bg = tb::COLOR.DEFAULT;
def fg = tb::COLOR.BLACK;
def paint_colors = [
(tb::COLOR.BLACK, "BLACK "),
(tb::COLOR.RED, "RED "),
(tb::COLOR.GREEN, "GREEN "),
(tb::COLOR.YELLOW, "YELLOW "),
(tb::COLOR.BLUE, "BLUE "),
(tb::COLOR.MAGENTA, "MAGENTA"),
(tb::COLOR.CYAN, "CYAN "),
];
def help_text = [
"Left-click to paint",
"Right-click to change color",
"Press q to exit",
];
def exit_keys = [
tb::KEY.ESC,
tb::KEY.CTRL_Z,
tb::KEY.CTRL_C,
tb::KEY.CTRL_D,
];
def exit_chars = [
'q',
'Q',
];
let ii: size = 0; // Current color index
fn handle_mouse_event(me: tb::mouse_event) bool = {
switch (me.key) {
case tb::KEY.MOUSE_LEFT => tb::set_cell(me.x, me.y, ' ',
tb::COLOR.DEFAULT, paint_colors[ii].0)!;
case tb::KEY.MOUSE_RIGHT => ii = (ii + 1) % len(paint_colors);
case => return false;
};
return false;
};
fn is_exit_key(ke: tb::key_event) bool = {
match (ke.key_or_ch) {
case let key: tb::key => for (let k .. exit_keys)
if (key == k) return true;
case let ch: rune => for (let c .. exit_chars)
if (ch == c) return true;
};
return false;
};
fn handle_events_and_exit() bool = {
let e = tb::poll_event();
if (e is tb::err)
return false;
return match (e as tb::event) {
case tb::resize_event => yield false;
case let me: tb::mouse_event => yield handle_mouse_event(me);
case let ke: tb::key_event => yield is_exit_key(ke);
};
};
fn print_help_text() void = {
let y = (tb::height()! - len(help_text)): int;
let len0 = tb::print(0, y, fg, bg, help_text[0])!;
let (c, ctext) = paint_colors[ii];
tb::print(len0: int + 1, y, c, bg, ctext)!;
for (let i = 1z; i < len(help_text); i += 1)
tb::print(0, y + i: int, fg, bg, help_text[i])!;
};
export fn main() void = {
let e = tb::init();
if (e is tb::err)
fmt::fatalf(tb::strerror(e as tb::err));
defer tb::shutdown()!;
tb::set_input_mode(tb::INPUT.ESC | tb::INPUT.MOUSE)!;
tb::set_clear_attrs(fg, bg)!;
for (true) {
print_help_text();
tb::present()!;
if (handle_events_and_exit()) break;
};
return;
};
|